+
+
diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java
new file mode 100644
index 000000000..d70aa4e7d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java
@@ -0,0 +1,97 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 example;
+
+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;
+import java.util.List;
+
+import org.apache.struts2.StrutsTestCase;
+
+public class ConfigTest extends StrutsTestCase {
+
+ protected void assertSuccess(String result) throws Exception {
+ assertTrue("Expected a success result!",
+ ActionSupport.SUCCESS.equals(result));
+ }
+
+ protected void assertInput(String result) throws Exception {
+ assertTrue("Expected an input result!",
+ ActionSupport.INPUT.equals(result));
+ }
+
+ protected Map assertFieldErrors(ActionSupport action) throws Exception {
+ assertTrue(action.hasFieldErrors());
+ return action.getFieldErrors();
+ }
+
+ protected void assertFieldError(Map field_errors, String field_name, String error_message) {
+
+ List errors = (List) field_errors.get(field_name);
+ assertNotNull("Expected errors for " + field_name, errors);
+ assertTrue("Expected errors for " + field_name, errors.size()>0);
+ // TODO: Should be a loop
+ assertEquals(error_message,errors.get(0));
+
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ XmlConfigurationProvider c = new XmlConfigurationProvider("struts.xml");
+ configurationManager.addConfigurationProvider(c);
+ configurationManager.reload();
+ }
+
+ protected ActionConfig assertClass(String namespace, String action_name, String class_name) {
+ RuntimeConfiguration configuration = configurationManager.getConfiguration().getRuntimeConfiguration();
+ ActionConfig config = configuration.getActionConfig(namespace, action_name);
+ assertNotNull("Mssing action", config);
+ assertTrue("Wrong class name: [" + config.getClassName() + "]",
+ class_name.equals(config.getClassName()));
+ return config;
+ }
+
+ protected ActionConfig assertClass(String action_name, String class_name) {
+ return assertClass("", action_name, class_name);
+ }
+
+ protected 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 testConfig() throws Exception {
+ assertNotNull(configurationManager);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java
new file mode 100644
index 000000000..9239a706e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 example;
+
+import com.opensymphony.xwork2.ActionSupport;
+import junit.framework.TestCase;
+
+public class HelloWorldTest extends TestCase {
+
+ public void testHelloWorld() throws Exception {
+ HelloWorld hello_world = new HelloWorld();
+ String result = hello_world.execute();
+ assertTrue("Expected a success result!",
+ ActionSupport.SUCCESS.equals(result));
+ assertTrue("Expected the default message!",
+ hello_world.getText(HelloWorld.MESSAGE).equals(hello_world.getMessage()));
+ }
+}
diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java
new file mode 100644
index 000000000..72b761dac
--- /dev/null
+++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 example;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+
+import java.util.Map;
+
+public class LoginTest extends ConfigTest {
+
+ public void FIXME_testLoginConfig() throws Exception {
+ ActionConfig config = assertClass("example", "Login_input", "example.Login");
+ assertResult(config, ActionSupport.SUCCESS, "Menu");
+ assertResult(config, ActionSupport.INPUT, "/example/Login.jsp");
+ }
+
+ public void testLoginSubmit() throws Exception {
+ Login login = new Login();
+ login.setUsername("username");
+ login.setPassword("password");
+ String result = login.execute();
+ assertSuccess(result);
+ }
+
+ // Needs access to an envinronment that includes validators
+ public void FIXME_testLoginSubmitInput() throws Exception {
+ Login login = new Login();
+ String result = login.execute();
+ assertInput(result);
+ Map errors = assertFieldErrors(login);
+ assertFieldError(errors,"username","Username is required.");
+ assertFieldError(errors,"password","Password is required.");
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/mailreader/README.txt b/STRUTS_2_0_X/apps/mailreader/README.txt
new file mode 100644
index 000000000..802aea4d4
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/README.txt
@@ -0,0 +1,18 @@
+README.txt - mailreader
+
+The MailReader demonstrates a localized application with a master/child
+CRUD workflow.
+
+This rendition also demonstrates using wildcards to "normalize" an
+application.
+
+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_2_0_X/apps/mailreader/pom.xml b/STRUTS_2_0_X/apps/mailreader/pom.xml
new file mode 100644
index 000000000..cc13cdd8d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.apache.struts
+ struts2-apps
+ 2.0.14
+
+ org.apache.struts
+ struts2-mailreader
+ war
+ Starter Webapp
+
+
+ scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader
+ scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader
+ http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader
+
+
+
+
+
+ javax.servlet
+ servlet-api
+ 2.4
+ provided
+
+
+ ${pom.groupId}
+ struts-mailreader-dao
+ 1.3.5
+
+
+
+
+
+
+ src/main/java
+
+ **/*.xml
+ **/*.properties
+
+
+
+
+
+ org.mortbay.jetty
+ maven-jetty-plugin
+ 6.0.1
+
+ 10
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties
new file mode 100644
index 000000000..03dbf277b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/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_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties
new file mode 100644
index 000000000..981adc82c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties
@@ -0,0 +1 @@
+.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==>
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml
new file mode 100644
index 000000000..0e7ed9669
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /pages/Error.jsp
+ /pages/Error.jsp
+ Login_input
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml
new file mode 100644
index 000000000..b1b1859f5
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+ /tour.html
+
+
+
+
+ /Welcome.jsp
+
+
+
+
+ Welcome
+
+
+
+ /Login.jsp
+ Welcome
+ MainMenu
+ ChangePassword
+
+
+
+
+
+ /Registration.jsp
+ MainMenu
+
+
+
+
+
+
+
+ /Subscription.jsp
+ Registration_input
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /{1}.jsp
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java
new file mode 100644
index 000000000..fabd98d6e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java
@@ -0,0 +1,234 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.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.*;
+
+/**
+ *
ServletContextListener 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.
+ *
+ *
IMPLEMENTATION WARNING - 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
+ * NOT assume that files written here will survive a restart
+ * of your servlet container.
+ *
+ *
This class was borrowed from the Shale Mailreader. Changes were:
+ *
+ *
+ *
+ *
Path to database.xml (under classes here).
+ *
+ *
Class to store protocol list (an array here).
+ *
+ *
+ *
+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
+ *
Initialize and load our initial database from persistent
+ * storage.
+ *
+ * @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
+
+
+ /**
+ *
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 = 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_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java
new file mode 100644
index 000000000..10cc36823
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/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_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java
new file mode 100644
index 000000000..f33b771dd
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java
@@ -0,0 +1,128 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+/**
+ *
Manifest constants for the MailReader application.
+ */
+public final class Constants {
+
+ // --- Tokens ----
+
+ /**
+ *
The token representing a "cancel" request.
+ */
+ public static final String CANCEL = "cancel";
+
+ /**
+ *
The token representing a "create" task.
+ */
+ public static final String CREATE = "Create";
+
+ /**
+ *
The application scope attribute under which our user database is
+ * stored.
+ */
+ public static final String DATABASE_KEY = "database";
+
+ /**
+ *
The token representing a "edit" task.
+ */
+ public static final String DELETE = "Delete";
+
+ /**
+ *
The token representing a "edit" task.
+ */
+ public static final String EDIT = "Edit";
+
+ /**
+ *
The package name for this application.
+ */
+ public static final String PACKAGE = "org.apache.struts.apps.mailreader";
+
+ /**
+ *
The session scope attribute under which the Subscription object
+ * currently selected by our logged-in User is stored.
+ */
+ public static final String SUBSCRIPTION_KEY = "subscription";
+
+ /**
+ *
The session scope attribute under which the User object for the
+ * currently logged in user is stored.
+ */
+ public static final String USER_KEY = "user";
+
+ /**
+ *
The token representing the "Host" property.
+ */
+ public static final String HOST = "host";
+
+
+ // ---- Error Messages ----
+
+ /**
+ *
+ * A static message in case message resource is not loaded.
+ *
+ */
+ public static final String ERROR_MESSAGES_NOT_LOADED =
+ "ERROR: Message resources not loaded -- check servlet container logs for error messages.";
+
+ /**
+ *
+ * A static message in case database resource is not loaded.
+ *
+ */
+ public static final String ERROR_DATABASE_NOT_LOADED =
+ "ERROR: User database not loaded -- check servlet container logs for error messages.";
+
+ /**
+ *
+ * A standard key from the message resources file, to test if it is available.
+ *
+ */
+ public static final String ERROR_DATABASE_MISSING = "error.database.missing";
+
+ /**
+ *
+ * A "magic" username to trigger an ExpiredPasswordException for testing.
+ *
+ */
+ public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException";
+
+ /**
+ *
+ * Name of field to associate with authentification errors.
+ *
+ */
+ public static final String LOG_DATABASE_SAVE_ERROR =
+ " Unexpected error when saving User: ";
+
+
+}
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml
new file mode 100644
index 000000000..4a04c7629
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java
new file mode 100644
index 000000000..0efa19b10
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+/**
+ *
Validate a user login.
+ */
+public final 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_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java
new file mode 100644
index 000000000..20732966a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+/**
+ *
Log user out of the current session.
+ */
+public class Logout extends MailreaderSupport {
+
+ public String execute() {
+
+ setUser(null);
+
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java
new file mode 100644
index 000000000..50ca23a5c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java
@@ -0,0 +1,582 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.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;
+
+/**
+ *
Base Action for MailreaderSupport application.
+ *
+ *
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.
+ */
+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;
+ }
+
+ /**
+ * Convenience method to copy User properties.
+ **/
+ protected void copyUser(User source, User target) {
+ if ((source==null) || (target==null)) return;
+ target.setFromAddress(source.getFromAddress());
+ target.setFullName(source.getFullName());
+ target.setPassword(source.getPassword());
+ target.setReplyToAddress(source.getReplyToAddress());
+ }
+
+ /**
+ * Convenience method to copy Subscription properties.
+ **/
+ protected void copySubscription(Subscription source, Subscription target) {
+ if ((source==null) || (target==null)) return;
+ target.setAutoConnect(source.getAutoConnect());
+ target.setPassword(source.getPassword());
+ target.setType(source.getType());
+ target.setUsername(source.getUsername());
+ }
+
+
+ // ---- ApplicationAware ----
+
+ /**
+ *
Field to store application context or its proxy.
+ *
+ *
The application context lasts for the life of the application. A
+ * reference to the database is stored in the application context at
+ * startup.
+ */
+ private Map application;
+
+ /**
+ *
Store a new application context.
+ *
+ * @param value A Map representing application state
+ */
+ public void setApplication(Map value) {
+ application = value;
+ }
+
+ /**
+ *
+ *
+ * @return Returns the User username.
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ *
Store new User username
+ *
+ * @param value The username to set.
+ */
+ public void setUsername(String value) {
+ username = value;
+ }
+
+ // ---- Database property ----
+
+ /**
+ *
Provide reference to UserDatabase, or null if the database is not
+ * available.
+ *
+ * @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;
+ }
+
+ /**
+ *
Verify input for creating a new user, create the user, and process
+ * the login.
+ *
+ * @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
+
+ /**
+ *
Use the current User object to create a new User object, and make
+ * the new User object the authenticated user.
+ *
+ *
The "current" User object is usually a temporary object being used
+ * to capture input.
+ *
+ * @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) {
+ copyUser(input,user);
+ setUser(user);
+ }
+ }
+
+ // ---- Subscription property ----
+
+ /**
+ *
Obtain uSER Subscription for the local Host property.
+ *
+ *
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());
+ }
+
+ /**
+ *
Provide a "temporary" User Subscription object that can be used to
+ * capture input values.
+ */
+ public void createInputSubscription() {
+ Subscription sub = new MemorySubscription(getUser(), null);
+ setSubscription(sub);
+ setHost(sub.getHost());
+ }
+
+ /**
+ *
Provide new User Subscription object for the given host, or null if
+ * the host is not unique.
+ *
+ * @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);
+ }
+
+ /**
+ *
Create a new Subscription from the current Subscription object,
+ * making the new Subscription the current Subscription.
+ *
+ *
Usually, the "current" Subscription is a temporary object being used
+ * to capture input values.
Provide MailServer Host for current User Subscription.
+ *
+ * @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_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties
new file mode 100644
index 000000000..6a0f3a547
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties
@@ -0,0 +1,96 @@
+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 login 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=
+errors.header=
Validation Error
You must correct the following error(s) before proceeding:
+errors.prefix=
+errors.suffix=
+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.login=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}
+login.title=MailReader Demonstration Application - Login
+mainMenu.heading=Main Menu Options for
+mainMenu.logout=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.
+host=Mail Server
+password=Password
+password2=(Repeat) Password
+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.autoConnect=Auto Connect
+subscription.password=Mail Password
+subscription.type=Server Type
+subscription.username=Mail Username
+subscription.title.create=Create New Mail Subscription
+subscription.title.delete=Delete Existing Mail Subscription
+subscription.title.edit=Edit Existing Mail Subscription
+
+user.fromAddress=From Address
+user.fullName=Full Name
+user.replyToAddress=Reply To Address
+
+# 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_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties
new file mode 100644
index 000000000..2b9d2e4b6
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/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=
+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.
+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.logout=\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_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml
new file mode 100644
index 000000000..689640742
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+ true
+ 4
+ 10
+
+
+
+
+
+
+
+
+
+
+
+ password eq password2
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml
new file mode 100644
index 000000000..44d66bc19
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java
new file mode 100644
index 000000000..635fc0d59
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java
@@ -0,0 +1,122 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+
+/**
+ *
Insert or update a User object to the persistent store.
Double check that there is not a valid User login.
+ *
+ * @return True if there is not a valid User login
+ */
+ private boolean isCreating() {
+ User user = getUser();
+ return (null == user) || (null == user.getDatabase());
+ }
+
+ /**
+ *
Retrieve User object to edit or null if User does not exist.
+ *
+ * @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;
+ }
+
+ /**
+ *
Insert or update a Registration.
+ *
+ * @return The "outcome" result code
+ * @throws Exception on any error
+ */
+ public String save() throws Exception {
+ return execute();
+ }
+
+ /**
+ *
Insert or update a User object to the persistent store.
+ *
+ *
If a User is not logged in, then a new User is created and
+ * automatically logged in. Otherwise, the existing User is updated.
+ *
+ * @return The "outcome" result code
+ * @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_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml
new file mode 100644
index 000000000..9f2f6d793
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml
new file mode 100644
index 000000000..df903c25b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java
new file mode 100644
index 000000000..a495986bc
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java
@@ -0,0 +1,145 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.xwork2.Preparable;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ *
Provide an Edit method for retrieving an existing subscription, and a
+ * Save method for updating or inserting a subscription.
Load User Subscription for the local Host property.
+ *
+ *
Usually, the Host is being set from the request by a link to an Edit
+ * or Delete task.
+ *
+ * @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;
+
+ }
+
+ /**
+ *
Prepare to present a confirmation page before removing
+ * Subscription.
+ *
+ * @return INPUT or Error, if Subscription is not found
+ */
+ public String delete() {
+
+ setTask(Constants.DELETE);
+ return find();
+ }
+
+ /**
+ *
Prepare to edit User Subscription.
+ *
+ * @return INPUT or Error, if Subscription is not found
+ */
+ public String edit() {
+
+ setTask(Constants.EDIT);
+ return find();
+ }
+
+ /**
+ *
Examine the Task property and DELETE, CREATE, or save the User
+ * Subscription, as appropriate.
+ *
+ * @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_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java
new file mode 100644
index 000000000..e43d6c463
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+/**
+ * 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_2_0_X/apps/mailreader/src/main/java/struts.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml
new file mode 100644
index 000000000..e0cbeb590
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt
new file mode 100644
index 000000000..dd5b3a58a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/resources/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_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt
new file mode 100644
index 000000000..cd13ec449
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Struts
+Copyright 2000-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp
new file mode 100644
index 000000000..ce543d79b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp
@@ -0,0 +1,25 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib uri="/struts-tags" prefix="s" %>
+
+
+
+
+ " rel="stylesheet"
+ type="text/css"/>
+
+
+
+
+
a1+>C+=E}g~yqGRj0%yfM+92a`l?u
zqbXi)U8Nb6FPI!3YO2>=lMS}+-6$Ij{4~(RFJAlkS2?yW&r+Ku+B+KE>iwCr;rs_j
z-|Li(&8dC#k=|H-S!7tONL
zLSqMdj~hCC)L0cSu-)nEJmLM^*Esvwt7{})7(H&%K4$wEWnJ%4T$)^@Nl@)$g}osj
i->jUKVkC}vXd1Hcsk_Ov^jjj=nWP5!`xzM`@BaX)9*BDY
literal 0
HcmV?d00001
diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html
new file mode 100644
index 000000000..8da35136d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html
@@ -0,0 +1,2470 @@
+
+
+
+
+
+
+
+ A Walking Tour of the Struts 2 MailReader Application
+
+
+
+
+
A Walking Tour of the Struts 2 MailReader Application
+
+
+
+ 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.
+
+
+
+
+
+ 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
+
+ Key Technologies Primer.
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ For more about the MailReader, including alternate implementations and a
+ set of formal Use Cases,
+ please visit the
+ Struts University MailReader site.
+
+
+
+
+
+ JAAS -
+ 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
+ Key Technologies Primer for more about
+ authentication technologies.)
+
+
+
+
+
+ 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).
+
+ 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.
+
+ 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".
+
+
+
+
web.xml - The Web Application Deployment Descriptor
+ You might note that the web.xml configuration does not specify which file extension
+ to use with actions.
+ The default extension for Struts 2 is ".action",
+ but the extension can be changed in the struts.properties file.
+ For compatability with prior releases, the MailReader uses a .do extension for actions.
+
+
+
+
struts.properties
+
struts.action.extension = do
+
+
+
+ The web.xml does specify a "Welcome File List" for the 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.
+
+
+
+ However, most Struts applications do not refer to physical pages,
+ but to "virtual resources" called actions.
+ 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.
+
+
+
+
Best Practice:
+
+
"Link actions not pages."
+
+
+
+
+ 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.
+
+
+
+
+ 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?
+
+
+
+ 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.
+
+
+
+
MailReader's index.html
+
<!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>
+
+
+
+ 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.
+
+ 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.
+
+ 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".
+
+
+
+ But if we peek at the configuration file for the MailReader,
+ we find a slightly more complicated XML element for the Welcome action.
+
+ Here, the Welcome 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".
+
+
+
+
Key concept:
+
+
+ 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.
+
+
+
+
+
+ The net effect is that all of the result details,
+ including the paths to server pages,
+ all can be declared once in the configuration.
+ Tightly coupled implementation details are not scattered all over
+ the application.
+
+
+
+
Key concept:
+
+
+ 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.
+
+
+
+
+
+
+ OK ... but why would a Welcome Action want to choose between "success" and
+ "error"?
+
+ 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 page, the Welcome
+ class checks to see if the database is available.
+
+
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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?
+
+
+
+ The database is created by a custom Listener that we configured in the "web.xml".
+
+ By default, our ApplicationListener loads a MemoryDatabase
+ 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.
+
+
+
+ The database comes seeded with a sample user.
+ If you check the "database.xml" file under "/src/main/resources",
+ you'll see the sample user described in XML.
+
+
+
+
The "seed" user element from the MailReader database.xml
+ As mentioned, MailReader is an internationalized application.
+ In Struts 2, message resources are associated with the Action class being processed.
+ If we check the source, we find a language resource bundle named
+ MailreaderSupport.
+ MailreaderSupport is our base class for all the MailReader Actions.
+ Since all of our Actions extend MailreaderSupport,
+ all of our Actions can use the same resource bundle.
+
+
+
+
Message Resource entries used by the Welcome page
+
index.heading=MailReader Application Options
+index.login=Log on to the MailReader Application
+index.registration=Register with the MailReader Application
+index.title=MailReader Demonstration Application
+index.tour=A Walking Tour of the MailReader Demonstration Application
+
+
+
+ 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.
+
+ 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".
+
+
+
+ (We use the tag prefix "s:" in the Struts 2 MailReader application,
+ but you can use whatever prefix you like in your applications.)
+
+
+
+ The text 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.
+
+
+
+ The url 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.
+
+
+
+
Tip:
+
+
+ Cookies -
+ 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.)
+
+
+
+
+
+ The i18n 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.
+
+
+
+ The alternate bundle is stored in the {{/src/main/resources}} folder,
+ so that it ends up under "classes", which is on the application's class path.
+
+
+
+ In the span of a single request for the Welcome page, the framework has done
+ quite a bit already:
+
+
+
+
+ Confirmed that required resources were loaded during initialization.
+
+
+
+ Written all the page headings and labels from internationalized
+ message resources.
+
+
+
+ Automatically URL-encoded paths as needed.
+
+
+
+
+ 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 Login link first.
+
+ The Login page displays a form that accepts a username and password.
+ You can use the default username and password to login
+ (user and pass), 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.
+
+ We already saw some of the tags used by the Login page on the Welcome page.
+ Let's focus on the new tags.
+
+
+
+ The first new tag on the Login page is actionerrors.
+ 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.
+
+
+
+ The second new tag is form.
+ This tag renders a HTML form tag.
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ The Struts Tags support templates and themes so that a set of HTML tags can be
+ rendered from a single Struts Tag. For example, the single tag
+
+ If for some reason you don't like the markup generated by a Struts 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:
+
+ 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
+ "template/simple/actionerror.ftl",
+ and place this one file at the base of your application's classpath.
+
+ Under the covers, the framework uses
+ Freemarker
+ for its standard templating language.
+ FreeMarker is similar to
+ Velocity,
+ 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 tags.
+
+
+
+ The password 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.)
+
+
+
+ Unsurprisingly, the submit and reset tags
+ render buttons of the corresponding types.
+
+ Here we are creating the Cancel button for the form.
+ The button's attribute action="Login_cancel"
+ tells the framework to submit to the Login's "cancel" method
+ instead of the usual "execute" method.
+ The onclick="form.onsubmit=null" 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 cancel method.
+ Another entry on the special-case list is the "input" method.
+
+
+
+
Tip:
+
+
+ The Struts Tags have options and capabilities beyond what we have shown here.
+ For more see, the
+ Struts Tag documentation.
+
+
+
+
+
+ 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?
+
+
+
+ For the answers, we need to look at another flavor of configuration file:
+ the "validation" file.
+
+ You may note that the DTD refers to "XWork".
+
+ Open Symphony XWork
+ is a generic command-pattern framework that can be used outside of a
+ web environment. Essentially, Struts 2 is a web-based extension of the
+ XWork framework.
+
+
+
+ The field elements correspond to the ActionForm properties.
+ The username and password 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.
+
+ If validation passes, the framework invokes the "execute" method of the Login Action.
+ The actual Login Action is brief, since most of the functionality derives
+ from the base class, MailreaderSupport.
+
+
+
+
Login.java
+
package mailreader2;
+import org.apache.struts.apps.mailreader.dao.User;
+public final 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;
+ }
+}
+
+
+
+ Login 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.
+
+ Let's look at the relevant properties and methods from MailreaderSupport
+ and another base class, ActionSupport, namely
+ "getUsername", "getPassword", "findUser", "setUser", and "hasErrors".
+
+
+
+ The framework lets you define
+ JavaBean properties
+ 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.
+
+
+
+ The Username and Password properties are nothing fancy,
+ just standard JavaBean properties.
+
+ We use these properties to capture the client's credentials,
+ and pass them to the more interesting findUser method.
+
+
+
+
MailreaderSupport.findUser
+
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) {
+ this.addFieldError("password", getText("error.password.mismatch"));
+ }
+ return user;
+}
+
+
+
+ The "findUser" method dips into the MailReader Data Access Object layer,
+ which is represented by the Database 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!
+
+
+
+
Best Practice:
+
+
+ "Strongly separate data access and business logic from the rest of
+ the application."
+
+
+
+
+
+ When "findUser" returns,
+ the Login Action looks to see if a valid (non-null) User object is returned.
+ A valid User is passed to the User property.
+ Although it is still a JavaBean property,
+ the User property is not implemented in quite the same way as Username and Password.
+
+
+
+
MailreaderSupport.setUser
+
public User getUser() {
+ return (User) getSession().get(Constants.USER_KEY);
+}
+public void setUser(User user) {
+ getSession().put(Constants.USER_KEY, user);
+}
+
+
+
+ Instead of using a field to store the property value,
+ "setUser" passes it to a Session property.
+
+ 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.
+
+
+
+ But, when MailreaderSupport is running inside a web application,
+ how does it acquire a reference to the servlet session?
+
+
+
+ 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.
+
+
+
+ The magic that provides the Session property a runtime value is called
+ "dependency injection".
+ The MailreaderSupport class implements a interface called SessionAware.
+ SessionAware is bundled with the framework,
+ and it defines a setter for the Session property.
+
+
+
+ public void setSession(Map session);
+
+
+
+ Also bundled with the framework is an object called the
+ ServletConfigInterceptor.
+ If the ServletConfigInterceptor sees that an Action implements the SessionAware interface,
+ it automatically set the session property.
+
+
+
if (action instanceof SessionAware) {
+ ((SessionAware) action).setSession(context.getSession());
+}
+
+
+ The framework uses these "Interceptor" classes to create a front controller
+ 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
+ Filters,
+ 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.)
+
+
+
+ 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 configuration.
+
+
+
+ Many Interceptors provide a utility or helper functions,
+ like setting the session property.
+ Others, like the ValidationInterceptor,
+ can change the workflow of an action.
+ Interceptors are key feature of the framework,
+ and we will see a few more on the tour.
+
+
+
+ If a valid User is not found, or the password doesn't match,
+ the "findUser" method invokes the addFieldError method to note the
+ problem.
+ When "findUser" returns, the Login Action checks for errors,
+ and then it returns either INPUT or SUCCESS.
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+
Best Practice:
+
+
"Use a base class to define common functionality."
+
+
+
+
+ But, what happens if Login returns INPUT instead of SUCCESS.
+ How does the framework know what to do next?
+
+
+
+ To answer that question,
+ we need to turn back to the Struts configuration
+ and look at how Login is declared.
+
+ The Login action element outlines how the Login workflow operates,
+ including what to do when the Action returns "input",
+ or the default result name "success".
+
+ You might notice that the name of the Login action element is not "Login"
+ but "Login_*".
+ The asterisk is a special "wildcard" notation that tells the framework to match any series
+ of character at this point.
+ In the method attribute,
+ the "{1}" notation indicates that framework should substitute whatever characters match
+ the asterisk at runtime.
+ When we cite actions like "Login_cancel" or "Login_input",
+ the framework matches "cancel" or "input" with the wildcard and fills in the blanks.
+
+
+
+ The "trailing bang" notation was hardwired into WebWork 2.
+ To provide backward compatibility,
+ the notation is supported by Struts 2.0.
+ If you prefer to use wildcards to emulate the same notation,
+ as the Mailreader does,
+ you should disable the old notation in the Struts properties file.
+
+
+
+
struts.properties
+
struts.enable.DynamicMethodInvocation = false
+
+
+
+ Using wildcards with a exclamation point (or "bang") is not the only way we can use
+ wilcards to invoke methods.
+ If we wanted to use actions like "inputLogin",
+ we could move the asterisk and use an action name like "*Login".
+
+
+
+ Within the Login 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
+ "Login.jsp" page.
+
+
+
+ The second result element is named cancel.
+ If someone presses the cancel button on the Login page,
+ the Action class will return "cancel", this result will be selected,
+ and the framework will issue a redirect to the Welcome action.
+
+
+
+ The third result has no name,
+ so it will be called if the default success token is returned.
+ So, if the Login succeeds,
+ control will transfer to the MainMenu action.
+
+
+
+ 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.
+
+
+
+ Just in case any other Exceptions are thrown,
+ the MailReader application also defines a global handler.
+
+ 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.
+
+
+
+
Error.jsp
+
<%@ 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>
+ <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>
+
+
+
+ The Error page uses property tags to expose
+ the Exception message and the Exception stack.
+
+
+
+ Finally, the Login action specifies an InterceptorStack
+ named defaultStack.
+ If you've worked with Struts 2 or WebWork 2 before, that might seem strange,
+ since "defaultStack" is the factory default.
+
+
+
+ In the MailReader application, most of the actions are only available
+ to authenticated users.
+ The exceptions are the Welcome, Login, and Register actions
+ which are available to everyone.
+ To authenticate clients,
+ the MailReader uses a custom Interceptor and a custom Interceptor stack.
+
+ The AuthenticationInterceptor 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 Login action.
+
+
+
+ The MailReader defines three custom Interceptor stacks: "user", "user-submit",
+ and "guest".
+
+ The user stacks require that the client be authenticated.
+ In other words, that a User object is present in the session.
+ The actions using a guest stack can be accessed by any client.
+ The -submit versions of each can be used with actions
+ with forms, to guard against double submits.
+
+
+
Double Submits
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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
+
+
+
+ Because the default interceptor stack will now authenticate the client,
+ we need to specify the standard "defaultStack" for the three
+ "guest actions", Welcome, Login, 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.
+
+ On a successful login, 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:
+
+
+
+
+ Edit your user registration profile
+
+
+ Log off MailReader Demonstration Application
+
+
+
+
+ Let's review the source for the "MainMenu" action mapping,
+ and the "MainMenu.jsp".
+
+ The source for "MainMenu.jsp" also contains a new tag,
+ property, which we use to customize the page with the
+ "fullName" property of the authenticated user.
+
+
+
+ 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.
+
+
+
+ The customized MainMenu page offers two standard links.
+ One is to "Edit your user registration profile".
+ The other is to "Logout the MailReader Demonstration Application".
+
+ 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.
+
+
+
+ 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.
+
+ 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.
+
+
+
+
Note:
+
+
+ Presention Logic -
+ 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.
+
+
+
+
+
+ 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.
+
+ 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 iterator
+ tag to display the User's Subscriptions.
+
+
+
+ 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.
+
+ Now look back at the code used to generate this block.
+
+
+ Notice anything nifty?
+
+
+ How about that the markup between the iterator tag is
+ actually simpler than the markup that we would use to render one row of the
+ table?
+
+
+ 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.
+
+
+ Nice trick!
+
+
+
+ The secret to this magic is the value stack.
+ 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.
+
+
+
+ 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.
+
+
+
+ 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.)
+
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+ 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,
+ on any object on the stack.
+
+
+
+ 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.
+
+
+
+ The Subscription list uses another new tag: the param 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.
+
+
+
+ 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.
+
+ 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 at the Subscription configuration
+ and follow the bouncing ball from page to action to page.
+
+ The Edit link specified the Subscription action,
+ but also includes the qualifier _edit.
+ The wildcard notation tells the framework to use any characters given after "Subscription_"
+ as the name of a method to invoke on the Action class,
+ instead of the default execute method.
+ The "alternate" execute methods are called alias methods.
+
+ 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.
+
+
+
+ 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.
+
+
+
+ The business logic for the "edit" alias is a simple wrapper
+ around the MailReader DAO classes.
+
+ 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 the
+ MailReader configuration will trap the exception for us.
+
+
+
+ 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 Login page automatically.
+
+
+
+ As a final layer of defense, we also configured a validator for Subscription,
+ to ensure that we are passed a Host parameter.
+
+ By keeping routine safety precautions out of the Action class,
+ the all-important Action becomes smaller and easier to maintain.
+
+
+
+ After setting the relevent Subscription object to the Subscription property,
+ the framework transfers control to the (you guessed it) Subscription page.
+
+ As before, we'll discuss the tags and attributes that are new to this page:
+ "token", "hidden", "label", "select", and "checkbox".
+
+
+
+ The token 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.
+
+
+
+ The hidden tag embeds the Task property into the form.
+ When the form is submitted,
+ the Subscription_save action will use the Task property to decide
+ whether to insert or update the form.
+
+
+
+ The label 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.
+
+
+
+ Saving the best for last, the Subscription form utilizes two more interesting
+ tags, "select" and "checkbox".
+
+
+
+ Unsurprisingly, the select tag renders a select control,
+ but the tag does so without requiring a lot of markup or redtape.
+
+ 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".
+
+
+
+
Subscription-validation.xml
+
public class Subscription 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());
+ }
+
+ // ...
+
+
+
+ The default Interceptor stack includes the PrepareInterceptor,
+ which observes the Preparable interface.
+
+ 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.
+
+ 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.
+
+
+
+ When writing web applications, the checkbox can be a tricky control.
+ 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 anything.
+ 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.
+
+
+
+ In Struts 1,
+ we use the reset method to work around checkbox issues.
+ In Struts 2, checkbox state is handled automatically.
+ The framework can detect when a checkbox tag has not been sent back,
+ and when that happens,
+ a default "false" value is used for the checkbox value.
+ No worries, mate.
+
+
+
+ If we press the SAVE button,
+ the form will be submitted to the Subscription_save action.
+ Since the save method needs some additional validation,
+ we can add a validation file.
+
+ The validators follow the same type of inheritance path as the classes.
+ SubscriptionSave extends Subscription,
+ so when Subscription_save is validated,
+ the Host property specified by "Subscription-validation.xml" will also be required.
+
+
+
+ If validation succeeds, the save method of Subscription will fire.
+
+ The copySubscription 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.
+
+
+
+ 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.
+
+
+
+ Another workaround is to declare only the immutable properties on the Action,
+ and then use what we can from the domain object.
+
+
+
+ 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.
+
+
+
+ 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.
+
+ 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.
+
+
+
Subscription Submit
+
+
+ When we pressed the SAVE button, there was one step that we overlooked.
+ The Mailreader application uses a "double submit" guard to keep people
+ from clicking the SAVE button multiple times and submitting the form again.
+
+
+
+ To add the double-submit guard, we can change the actions default processing
+ stack to user-submit.
+ But, we don't want to just copy and paste the other action settings from
+ the main Subscription action.
+ What we can do is put the subscription actions in their own package,
+ so that they can share result types.
+
+ Aftering a successful save,
+ the Subscription Action will return "success",
+ and the framework will redirect us back to Registration input.
+
+
+
Summary
+
+ 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
+
+ available online
+ and in the distribution.
+
+
+
+ Enjoy!
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/pom.xml b/STRUTS_2_0_X/apps/pom.xml
new file mode 100644
index 000000000..6ddea6129
--- /dev/null
+++ b/STRUTS_2_0_X/apps/pom.xml
@@ -0,0 +1,170 @@
+
+ 4.0.0
+
+ org.apache.struts
+ struts2-parent
+ 2.0.14
+
+ org.apache.struts
+ struts2-apps
+ pom
+ Webapps
+
+ blank
+ mailreader
+ portlet
+ showcase
+
+
+
+ scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps
+ scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps
+ http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps
+
+
+
+
+ apache-site
+ scp://people.apache.org/www/struts.apache.org/struts2/apps
+
+
+
+
+
+ hostedqa
+
+
+ com.hostedqa
+ hostedqa-remote-ant
+ 1.0-SNAPSHOT
+ test
+
+
+
+
+ codehaus
+ codehaus
+ http://repository.codehaus.org
+
+
+ maven-hostedqa
+ maven-hostedqa
+
+ true
+ always
+ ignore
+
+
+ true
+
+ http://maven.hostedqa.com
+
+
+
+
+
+
+ src/main/java
+
+ **/*.properties
+ **/*.xml
+
+
+
+
+
+ maven-antrun-plugin
+ org.apache.maven.plugins
+
+
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+ com.hostedqa
+ hostedqa-remote-ant
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+
+
+
+
+
+ org.codehaus.cargo
+ cargo-maven2-plugin
+ 0.3.1
+
+
+ tomcat5x
+ ${cargo.tomcat5x.home}
+ ${project.build.directory}/tomcat5x.log
+
+
+
+ ${project.build.directory}/tomcat5x
+
+
+
+
+
+ maven-antrun-plugin
+
+
+ copy-sources
+ process-sources
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+ ${pom.artifactId}
+
+
+
+
+
+
+ org.apache.struts
+ struts2-core
+ ${pom.version}
+
+
+
+ org.springframework
+ spring-mock
+ 2.0.1
+ test
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/README.txt b/STRUTS_2_0_X/apps/portlet/README.txt
new file mode 100644
index 000000000..efcb67bbc
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/README.txt
@@ -0,0 +1,17 @@
+README.txt - portlet
+
+This is a simple example of using the portlet API with Struts applications.
+
+For more on getting started with Struts, see
+
+* http://cwiki.apache.org/WW/home.html
+
+WARNING - Additional configuration required for deployment
+
+Due to difference in portlet contrainer implementations, the porlet
+WAR is not ready-to-run. Extract the porlet WAR, and then copy the
+contents of apps/portlet/src/main/etc// into the
+WAR's WEB-INF directory.
+
+
+----------------------------------------------------------------------------
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/portlet/pom.xml b/STRUTS_2_0_X/apps/portlet/pom.xml
new file mode 100644
index 000000000..8cf601fe0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/pom.xml
@@ -0,0 +1,80 @@
+
+
+ 4.0.0
+
+ org.apache.struts
+ struts2-apps
+ 2.0.14
+
+ org.apache.struts
+ struts2-portlet
+ war
+ Portlet Webapp
+
+
+ scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/portlet
+ scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/portlet
+ http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/portlet
+
+
+
+
+ portlet-api
+ portlet-api
+ 1.0
+ provided
+
+
+ org.apache.struts
+ struts2-spring-plugin
+ ${pom.version}
+
+
+ javax.servlet
+ servlet-api
+
+
+
+
+ org.apache.struts
+ struts2-core
+ ${pom.version}
+
+
+ velocity
+ velocity
+ 1.4
+
+
+
+ velocity-tools
+ velocity-tools
+ 1.1
+
+
+ commons-digester
+ commons-digester
+ 1.8
+
+
+ commons-lang
+ commons-lang
+ 2.1
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.1.1
+
+
+ commons-collections
+ commons-collections
+ 3.1
+
+
+ log4j
+ log4j
+ 1.2.12
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml
new file mode 100644
index 000000000..675c913d0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml
@@ -0,0 +1,63 @@
+
+
+
+ struts-portlet
+
+
+ contextConfigLocation
+ /WEB-INF/applicationContext*.xml
+
+
+ action2
+
+ org.apache.struts2.dispatcher.FilterDispatcher
+
+
+
+
+ action2
+ /*
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ org.apache.struts2.portlet.context.ServletContextHolderListener
+
+
+
+
+ org.exoplatform.services.portletcontainer.impl.servlet.PortletApplicationListener
+
+
+
+
+ preparator
+
+ org.apache.struts2.portlet.context.PreparatorServlet
+
+
+
+ dwr
+ uk.ltd.getahead.dwr.DWRServlet
+
+
+ PortletWrapper
+
+ org.exoplatform.services.portletcontainer.impl.servlet.ServletWrapper
+
+
+
+
+ dwr
+ /dwr/*
+
+
+ PortletWrapper
+ /PortletWrapper
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt
new file mode 100644
index 000000000..e502e0699
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt
@@ -0,0 +1,2 @@
+Put the empty 'struts-portlet' file in the $CATALINA_HOME/webapps/gridsphere/WEB-INF/CustomPortal/portlets
+folder of your Gridsphere installation. You will need to add the gridsphere-ui-tags-2.1.2.jar to your project.
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml
new file mode 100644
index 000000000..ed15d11cb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ JSR Portlet Servlet
+ PortletServlet
+
+
+
+
+ Portlet Servlet
+ en
+
+ Portlet Servlet
+ Portlet Servlet
+ A JSR Portlet Loader
+ portlet servlet
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml
new file mode 100644
index 000000000..d04e4e7b1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml
@@ -0,0 +1,10 @@
+
+
+ StrutsPortlet
+ StrutsPortlet Example Application
+ PUBLIC
+
+ struts-portlet#StrutsPortlet
+ USER
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml
new file mode 100644
index 000000000..14a160bd9
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml
@@ -0,0 +1,19 @@
+
+
+ StrutsPortlet Example
+
+
+ StrutsPortlet Example Application
+
+
+
+
+ struts-portlet#StrutsPortlet
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/struts-portlet b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/struts-portlet
new file mode 100644
index 000000000..e69de29bb
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml
new file mode 100644
index 000000000..e453c960b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml
@@ -0,0 +1,63 @@
+
+
+
+ struts-portlet
+
+
+ contextConfigLocation
+ /WEB-INF/applicationContext*.xml
+
+
+ action2
+
+ org.apache.struts2.dispatcher.FilterDispatcher
+
+
+
+
+ action2
+ /*
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ org.apache.struts2.portlet.context.ServletContextHolderListener
+
+
+
+
+ org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet
+
+
+
+
+ preparator
+
+ org.apache.struts2.portlet.context.PreparatorServlet
+
+
+
+ dwr
+ uk.ltd.getahead.dwr.DWRServlet
+
+
+ PortletServlet
+
+ org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet
+
+
+
+
+ dwr
+ /dwr/*
+
+
+ PortletServlet
+ /jsr/struts-portlet
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml
new file mode 100644
index 000000000..02e09d53b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml
@@ -0,0 +1,3 @@
+
+ struts-portlet
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml
new file mode 100644
index 000000000..663eaf395
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml
@@ -0,0 +1,12 @@
+
+
+ StrutsPortlet
+
+
+
+
+ StrutsPortlet2
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml
new file mode 100644
index 000000000..9d9c645cc
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml
new file mode 100644
index 000000000..c22073d5c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml
@@ -0,0 +1,11 @@
+
+
+
+ StrutsPortletInstance
+ StrutsPortlet
+
+
+ StrutsPortlet2Instance
+ StrutsPortlet2
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml
new file mode 100644
index 000000000..255c4530d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml
@@ -0,0 +1,18 @@
+
+ default
+
+ struts-portlet
+
+ StrutsPortletWindow
+ struts-portlet.StrutsPortlet.StrutsPortletInstance
+ left
+ 0
+
+
+ StrutsPortletWindow2
+ struts-portlet.StrutsPortlet2.StrutsPortlet2Instance
+ right
+ 0
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml
new file mode 100644
index 000000000..02e09d53b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml
@@ -0,0 +1,3 @@
+
+ struts-portlet
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml
new file mode 100644
index 000000000..663eaf395
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml
@@ -0,0 +1,12 @@
+
+
+ StrutsPortlet
+
+
+
+
+ StrutsPortlet2
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml
new file mode 100644
index 000000000..9d9c645cc
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml
new file mode 100644
index 000000000..2e062ad2a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml
@@ -0,0 +1,25 @@
+
+
+
+ overwrite
+ default
+
+
+ StrutsPortlet Example
+
+
+ StrutsWindow
+ StrutsPortletInstance
+ center
+ 0
+
+
+
+
+ overwrite
+
+ StrutsPortletInstance
+ struts-portlet.StrutsPortlet
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt
new file mode 100644
index 000000000..acde566d3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt
@@ -0,0 +1 @@
+Copy the struts-portlet.psml file to the JETSPEED2_INSTALL_DIR/webapps/jetspeed/WEB-INF/pages directory.
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml
new file mode 100644
index 000000000..d6c795489
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml
@@ -0,0 +1,20 @@
+
+
+ Struts Portlet Example Application
+ Struts Portlet Example Application
+
+
+
+
+
+
+
+
+
+ public-view
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml
new file mode 100644
index 000000000..b5fedfbad
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml
@@ -0,0 +1,75 @@
+
+
+
+ struts-portlet
+
+ contextConfigLocation
+ /WEB-INF/applicationContext*.xml
+
+
+ company_id
+ struts.apache.org
+
+
+ action2
+
+ org.apache.struts2.dispatcher.FilterDispatcher
+
+
+
+
+ action2
+ /*
+
+
+
+ com.liferay.portal.servlet.PortletContextListener
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ org.apache.struts2.portlet.context.ServletContextHolderListener
+
+
+
+
+
+ StrutsPortlet
+
+ com.liferay.portal.servlet.PortletServlet
+
+
+ portlet-class
+
+ org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher
+
+
+ 0
+
+
+
+ preparator
+
+ org.apache.struts2.portlet.context.PreparatorServlet
+
+
+
+ dwr
+ uk.ltd.getahead.dwr.DWRServlet
+
+
+
+ dwr
+ /dwr/*
+
+
+ StrutsPortlet
+ /StrutsPortlet/*
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java
new file mode 100644
index 000000000..d3e0741b2
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java
@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import java.util.Map;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionSupport;
+
+public class ExampleAction extends ActionSupport {
+
+ private String name = "PortletWork Example";
+
+ public String getName() {
+ return name;
+ }
+
+ public Map getRenderParameters() {
+ return ActionContext.getContext().getParameters();
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java
new file mode 100644
index 000000000..36d27965c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class FormExample extends ActionSupport {
+
+ String firstName = null;
+ String lastName = null;
+ public String execute() throws Exception {
+ // TODO Auto-generated method stub
+ return super.execute();
+ }
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+ public String displayResult() {
+ return "displayResult";
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java
new file mode 100644
index 000000000..1eee98b24
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java
@@ -0,0 +1,37 @@
+/*
+ * $Id: FormExample.java 471756 2006-11-06 15:01:43Z husted $
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import org.apache.struts2.portlet.example.model.Name;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ModelDriven;
+
+/**
+ */
+public class FormExampleModelDriven extends ActionSupport implements ModelDriven {
+
+ private Name name = new Name();
+
+ public Name getModel() {
+ return name;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java
new file mode 100644
index 000000000..a26609c13
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class FormExampleWithValidation extends ActionSupport {
+ private String firstName = null;
+ private String lastName = null;
+
+ public String input() {
+ return SUCCESS;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java
new file mode 100644
index 000000000..6e9aeae22
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import java.util.Collection;
+import java.util.Map;
+
+import javax.portlet.RenderRequest;
+
+import org.apache.struts2.portlet.context.PortletActionContext;
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class FormResultAction extends ActionSupport {
+
+ private String result = null;
+
+ public String getResult() {
+ return result;
+ }
+ public void setResult(String result) {
+ this.result = result;
+ }
+
+ public Collection getRenderParams() {
+ RenderRequest req = PortletActionContext.getRenderRequest();
+ Map params = req.getParameterMap();
+ return params.entrySet();
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java
new file mode 100644
index 000000000..ebbe102df
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class FormTestAction extends ActionSupport {
+
+ private String name = null;
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java
new file mode 100644
index 000000000..1998e3796
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java
@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.PortletPreferences;
+
+import org.apache.struts2.portlet.context.PortletActionContext;
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class SavePrefsAction extends ActionSupport {
+ private String preferenceOne = null;
+ private String preferenceTwo = null;
+ public String getPreferenceOne() {
+ return preferenceOne;
+ }
+ public void setPreferenceOne(String preferenceOne) {
+ this.preferenceOne = preferenceOne;
+ }
+ public String getPreferenceTwo() {
+ return preferenceTwo;
+ }
+ public void setPreferenceTwo(String preferenceTwo) {
+ this.preferenceTwo = preferenceTwo;
+ }
+
+ public String execute() throws Exception {
+ ActionRequest req = PortletActionContext.getActionRequest();
+ PortletPreferences prefs = req.getPreferences();
+ prefs.setValue("preferenceOne", preferenceOne);
+ prefs.setValue("preferenceTwo", preferenceTwo);
+ prefs.store();
+ return SUCCESS;
+ }
+
+ public String showForm() throws Exception {
+ PortletPreferences prefs = PortletActionContext.getRequest().getPreferences();
+ preferenceOne = prefs.getValue("preferenceOne", "not set");
+ preferenceTwo = prefs.getValue("preferenceTwo", "not set");
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java
new file mode 100644
index 000000000..c021714d3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java
@@ -0,0 +1,81 @@
+/*
+ * $Id: $
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example.fileupload;
+
+import java.io.File;
+
+import org.apache.struts2.dispatcher.DefaultActionSupport;
+
+/**
+ * File Upload example's action. FileUploadAction
+ *
+ */
+public class FileUploadAction extends DefaultActionSupport {
+
+ private static final long serialVersionUID = 5156288255337069381L;
+
+ private String contentType;
+ private File upload;
+ private String fileName;
+ private String caption;
+
+ // since we are using the file name will be
+ // obtained through getter/setter of FileName
+ public String getUploadFileName() {
+ return fileName;
+ }
+ public void setUploadFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+
+ // since we are using the content type will be
+ // obtained through getter/setter of ContentType
+ public String getUploadContentType() {
+ return contentType;
+ }
+ public void setUploadContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+
+ // since we are using the File itself will be
+ // obtained through getter/setter of
+ public File getUpload() {
+ return upload;
+ }
+ public void setUpload(File upload) {
+ this.upload = upload;
+ }
+
+
+ public String getCaption() {
+ return caption;
+ }
+ public void setCaption(String caption) {
+ this.caption = caption;
+ }
+
+ public String upload() throws Exception {
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java
new file mode 100644
index 000000000..1e59e1187
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java
@@ -0,0 +1,18 @@
+package org.apache.struts2.portlet.example.model;
+
+public class Name {
+ private String firstName;
+ private String lastName;
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java
new file mode 100644
index 000000000..8688423d6
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example.spring;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class SpringAction extends ActionSupport {
+
+ private ThingManager thingManager = null;
+ private String thing = null;
+
+ public void setThingManager(ThingManager thingManager) {
+ this.thingManager = thingManager;
+ }
+
+ public List getThings() {
+ return thingManager.getThings();
+ }
+
+ public String getThing() {
+ return thing;
+ }
+
+ public void setThing(String thing) {
+ this.thing = thing;
+ }
+
+ public String execute() {
+ if(StringUtils.isNotEmpty(thing)) {
+ thingManager.addThing(thing);
+ }
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java
new file mode 100644
index 000000000..ba117a5a7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.portlet.example.spring;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+public class ThingManager {
+ private List things = new ArrayList();
+
+ public void addThing(String thing) {
+ things.add(thing);
+ }
+
+ public List getThings() {
+ return things;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt
new file mode 100644
index 000000000..dd5b3a58a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/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_2_0_X/apps/portlet/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt
new file mode 100644
index 000000000..cd13ec449
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Struts
+Copyright 2000-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml
new file mode 100644
index 000000000..c6803daad
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml
new file mode 100644
index 000000000..4effe04b1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ You must enter a first name
+
+
+
+
+ You must enter a last name
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml
new file mode 100644
index 000000000..73ec598dc
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+ /WEB-INF/edit/index.jsp
+
+
+ /WEB-INF/edit/test.jsp
+
+
+
+ /WEB-INF/edit/formExampleInput.jsp
+
+
+
+
+
+ /WEB-INF/edit/formExampleInput.jsp
+
+
+ /edit/processFormExampleForward.action?firstName=${firstName}&lastName=${lastName}
+
+
+
+
+
+ /WEB-INF/edit/formExample.jsp
+
+
+
+
+
+
+ /WEB-INF/edit/namespaceTest.jsp
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml
new file mode 100644
index 000000000..742a8d29c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ /WEB-INF/help/index.jsp
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml
new file mode 100644
index 000000000..2fa0b21fb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+ /WEB-INF/view/index.jsp
+
+
+
+
+ /WEB-INF/view/formExampleInput.jsp
+
+
+
+
+
+ /WEB-INF/view/formExampleInput.jsp
+
+
+ /WEB-INF/view/formExample.jsp
+
+
+
+
+
+ /WEB-INF/view/formExampleInputPrg.jsp
+
+
+ formExamplePrg
+ displayResult
+ ${firstName}
+ ${lastName}
+
+
+ /WEB-INF/view/formExample.jsp
+
+
+
+
+
+ /WEB-INF/view/formExampleInputModelDriven.jsp
+
+
+ /WEB-INF/view/formExample.jsp
+
+
+
+
+
+ /WEB-INF/view/formExampleInputValidation.jsp
+
+
+
+
+
+ /WEB-INF/view/formExample.jsp
+
+
+ /WEB-INF/view/formExampleInputValidation.jsp
+
+
+
+
+
+ /WEB-INF/view/fileUpload.jsp
+
+
+ /WEB-INF/view/fileUploadSuccess.jsp
+
+
+
+
+
+ /WEB-INF/view/tokenExampleInput.jsp
+
+
+
+
+
+ /WEB-INF/view/tokenExampleInput.jsp
+
+
+ /WEB-INF/view/tokenExampleInput.jsp
+
+
+ /WEB-INF/view/tokenExample.jsp
+
+
+
+
+
+
+ /WEB-INF/view/springExample.jsp
+
+
+
+
+
+ /WEB-INF/view/freeMarkerExampleInput.ftl
+
+
+
+
+ /view/processFreeMarkerView.action?firstName=${firstName}&lastName=${lastName}
+
+
+
+ /WEB-INF/view/freeMarkerExample.ftl
+
+
+
+ /WEB-INF/view/helloWorld.vm
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties
new file mode 100644
index 000000000..cb40069a7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties
@@ -0,0 +1 @@
+struts.objectFactory = spring
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml
new file mode 100644
index 000000000..f348c9f95
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm
new file mode 100644
index 000000000..6d952f938
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm
@@ -0,0 +1,12 @@
+
+">Set some prefs
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp
new file mode 100644
index 000000000..7d62563ab
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp
@@ -0,0 +1,5 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+
Hello
+
+">Back to front page
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp
new file mode 100644
index 000000000..43c981df6
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp
@@ -0,0 +1,8 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+
Input your name
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp
new file mode 100644
index 000000000..6b03c99f3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp
@@ -0,0 +1,11 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+There are no examples in edit mode yet
+
+
+">Test
+
+">Form test
+
+">Dummy test
+
+">Back to view mode
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp
new file mode 100644
index 000000000..7e373a131
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp
@@ -0,0 +1,4 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+">Test page for namespace /edit/test
+
+">Back to edit index
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp
new file mode 100644
index 000000000..af8b02cd7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp
@@ -0,0 +1,6 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp
new file mode 100644
index 000000000..6aca664f1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp
@@ -0,0 +1,5 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+The preferences has been saved.
+
+">Back
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp
new file mode 100644
index 000000000..615860c47
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp
@@ -0,0 +1,4 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+">Test page
+
+">Back to edit index
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp
new file mode 100644
index 000000000..c8fb774f7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp
@@ -0,0 +1 @@
+This is the default help page!
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp
new file mode 100644
index 000000000..ea58ff820
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp
@@ -0,0 +1 @@
+There are no examples in help mode yet
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml
new file mode 100644
index 000000000..91e7c1eba
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml
@@ -0,0 +1,132 @@
+
+
+
+
+
+ Struts Test Portlet
+ StrutsPortlet
+ Struts Test Portlet
+
+ org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher
+
+
+
+ viewNamespace
+ /view
+
+
+
+
+ defaultViewAction
+ index
+
+
+
+
+ editNamespace
+ /edit
+
+
+
+
+ defaultEditAction
+ index
+
+
+
+
+ helpNamespace
+ /help
+
+
+
+
+ defaultHelpAction
+ index
+
+
+ 0
+
+
+ text/html
+ edit
+ help
+ view
+
+
+ en
+
+
+ My StrutsPortlet portlet
+ SP
+ struts,portlet
+
+
+
+
+ Struts Test Portlet2
+ StrutsPortlet2
+ Struts Test Portlet2
+
+ org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher
+
+
+
+ viewNamespace
+ /view
+
+
+
+
+ defaultViewAction
+ index
+
+
+
+
+ editNamespace
+ /edit
+
+
+
+
+ defaultEditAction
+ index
+
+
+
+
+ helpNamespace
+ /help
+
+
+
+
+ defaultHelpAction
+ index
+
+
+ 0
+
+
+ text/html
+ edit
+ help
+ view
+
+
+ en
+
+
+ My StrutsPortlet portlet2
+ SP2
+ struts,portlet
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt
new file mode 100644
index 000000000..53633149c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt
@@ -0,0 +1,10 @@
+Configurations:
+
+JBoss Portal specific configuration files
+-----------------------------------------
+jboss-app.xml
+jboss-portlet.xml
+jboss-web.xml
+portlet-instances.xml
+struts-example-object.xml
+struts-example-pages.xml
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp
new file mode 100644
index 000000000..e24ec7c17
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp
@@ -0,0 +1 @@
+
Hello from Ajax!
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp
new file mode 100644
index 000000000..796b0d77d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp
@@ -0,0 +1 @@
+This data is fetched via Ajax! The server time is <%= new java.util.Date() %>
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp
new file mode 100644
index 000000000..79ed4aa21
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp
@@ -0,0 +1,48 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+">
+This is a tabbed pane with two panels that fetches data from a remote action via ajax
+
+
+
+ This is the left pane
+
+
+
+
+
+ " id="ryh1" theme="ajax" label="remote one" />
+
+ middle tab
+
+
+
+
+
+ " id="ryh21" theme="ajax" label="remote right" />
+
+
+
+A DIV that waits for 5 seconds before loading the contents
+"
+ delay="5000"
+ loadingText="loading...">
+ Waiting for data
+
+A DIV that is updated every 2 seconds
+"
+ theme="ajax"
+ delay="2000"
+ updateFreq="2000"
+ errorText="There was an error"
+ loadingText="loading...">Initial Content
+
+
+">Back to front page
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp
new file mode 100644
index 000000000..bf702bdbf
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp
@@ -0,0 +1,13 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+
Example of Spring managed singleton. All the 'things' are contained in a Spring defined ThingManager
+
+Things in the list:
+
+
+
+
+
+
+
+
+
+
+">Back to front page
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp
new file mode 100644
index 000000000..e41c9e96e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp
@@ -0,0 +1,5 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+
The form was successfully submitted with a valid token
+
+"/>Back to front page
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp
new file mode 100644
index 000000000..7aa2e31aa
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp
@@ -0,0 +1,20 @@
+<%@ taglib prefix="s" uri="/struts-tags" %>
+
+ ERROR:
+
+
+
+
+
+
+
Form with invalid token
+
+
+
+
+
Form with valid token
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..4b64cb5b2
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+ contextConfigLocation
+ /WEB-INF/applicationContext*.xml
+
+
+
+ Struts2
+ org.apache.struts2.dispatcher.FilterDispatcher
+
+
+
+ Struts2
+ /*
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css b/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css
new file mode 100644
index 000000000..3dafc085a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css
@@ -0,0 +1,7 @@
+.wwFormTable {}
+.label {font-style:italic; }
+.errorLabel {font-style:italic; color:red; }
+.errorMessage {font-weight:bold; text-align: center; color:red; }
+.checkboxLabel {}
+.checkboxErrorLabel {color:red; }
+.required {color:red;}
diff --git a/STRUTS_2_0_X/apps/showcase/README.txt b/STRUTS_2_0_X/apps/showcase/README.txt
new file mode 100644
index 000000000..4d483c78c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/README.txt
@@ -0,0 +1,10 @@
+README.txt - showcase
+
+Showcase is a collection of examples with code that you might be adopt and
+adapt in your own applications.
+
+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_2_0_X/apps/showcase/pom.xml b/STRUTS_2_0_X/apps/showcase/pom.xml
new file mode 100644
index 000000000..f24c0b8d8
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/pom.xml
@@ -0,0 +1,185 @@
+
+
+ 4.0.0
+
+ org.apache.struts
+ struts2-apps
+ 2.0.14
+
+ org.apache.struts
+ struts2-showcase
+ war
+ Showcase Webapp
+
+
+ scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/showcase
+ scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/showcase
+ http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/showcase
+
+
+
+
+
+ hostedqa
+
+ 12
+ 9
+ 8
+ 7
+
+
+
+
+
+
+ org.apache.struts
+ struts2-struts1-plugin
+ ${pom.version}
+
+
+
+ org.apache.struts
+ struts2-jsf-plugin
+ ${pom.version}
+
+
+
+ org.apache.struts
+ struts2-config-browser-plugin
+ ${pom.version}
+
+
+
+ org.apache.struts
+ struts2-sitemesh-plugin
+ ${pom.version}
+
+
+
+ org.apache.struts
+ struts2-tiles-plugin
+ ${pom.version}
+
+
+
+ org.apache.tiles
+ tiles-jsp
+ 2.0.4
+ runtime
+
+
+
+ org.apache.struts
+ struts2-codebehind-plugin
+ ${pom.version}
+
+
+
+ org.apache.struts
+ struts2-spring-plugin
+ ${pom.version}
+
+
+
+ javax.servlet
+ servlet-api
+ 2.4
+ provided
+
+
+
+
+ velocity
+ velocity
+ 1.4
+
+
+
+ velocity-tools
+ velocity-tools
+ 1.1
+
+
+
+
+ opensymphony
+ sitemesh
+ 2.2.1
+
+
+ uk.ltd.getahead
+ dwr
+ 1.1-beta-3
+
+
+ log4j
+ log4j
+ 1.2.9
+
+
+ commons-logging
+ commons-logging
+ 1.0.4
+
+
+ org.apache.myfaces.core
+ myfaces-impl
+ 1.1.2
+
+
+ org.apache.myfaces.core
+ myfaces-api
+ 1.1.2
+
+
+ commons-fileupload
+ commons-fileupload
+ 1.1.1
+
+
+
+
+
+
+
+
+ org.mortbay.jetty
+ maven-jetty-plugin
+ 6.0.1
+
+ 10
+
+
+
+ org.apache.myfaces.core
+ myfaces-impl
+ 1.1.2
+
+
+ org.apache.myfaces.core
+ myfaces-api
+ 1.1.2
+
+
+ log4j
+ log4j
+ 1.2.9
+
+
+
+
+
+
+
+ src/main/resources
+
+
+ src/main/java
+
+ **/*.java
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java
new file mode 100644
index 000000000..c84e0b5a2
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java
@@ -0,0 +1,106 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * DateAction
+ *
+ */
+public class DateAction extends ActionSupport {
+
+ private static DateFormat DF = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
+
+ private Date now;
+ private Date past;
+ private Date future;
+ private Date after;
+ private Date before;
+
+
+ public String getDate() {
+ return DF.format(new Date());
+ }
+
+
+ /**
+ * @return Returns the future.
+ */
+ public Date getFuture() {
+ return future;
+ }
+
+ /**
+ * @return Returns the now.
+ */
+ public Date getNow() {
+ return now;
+ }
+
+ /**
+ * @return Returns the past.
+ */
+ public Date getPast() {
+ return past;
+ }
+
+ /**
+ *
+ * @return Returns the before date.
+ */
+ public Date getBefore() {
+ return before;
+ }
+
+ /**
+ *
+ * @return Returns the after date.
+ */
+ public Date getAfter() {
+ return after;
+ }
+
+ /**
+ */
+ public String browse() throws Exception {
+ Calendar cal = GregorianCalendar.getInstance();
+ now = cal.getTime();
+ cal.roll(Calendar.DATE, -1);
+ cal.roll(Calendar.HOUR, -3);
+ past = cal.getTime();
+ cal.roll(Calendar.DATE, 2);
+ future = cal.getTime();
+
+ cal.roll(Calendar.YEAR, -1);
+ before = cal.getTime();
+
+ cal.roll(Calendar.YEAR, 2);
+ after = cal.getTime();
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java
new file mode 100644
index 000000000..5d22be5ef
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import org.apache.struts2.showcase.ajax.tree.Category;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+//START SNIPPET: treeExampleDynamicJavaSelected
+
+public class DynamicTreeSelectAction extends ActionSupport {
+
+ private long nodeId;
+ private Category currentCategory;
+
+
+ public void setNodeId(long nodeId) {
+ this.nodeId = nodeId;
+ }
+ public long getNodeId() {
+ return nodeId;
+ }
+
+
+ public String execute() throws Exception {
+ currentCategory = Category.getById(nodeId);
+ return SUCCESS;
+ }
+
+
+ public String getNodeName() {
+ return currentCategory.getName();
+ }
+}
+
+//START SNIPPET: treeExampleDynamicJavaSelected
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java
new file mode 100644
index 000000000..3649b039b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java
@@ -0,0 +1,286 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class LotsOfOptiontransferselectAction extends ActionSupport {
+
+ private List _favouriteCartoonCharactersKeys;
+ private List _notFavouriteCartoonCharactersKeys;
+
+ private List _favouriteCarsKeys;
+ private List _notFavouriteCarsKeys;
+
+ private List _favouriteMotorcyclesKeys;
+ private List _notFavouriteMotorcyclesKeys;
+
+ private List _favouriteCountriesKeys;
+ private List _notFavouriteCountriesKeys;
+
+ private List _favouriteSportsKeys;
+ private List _nonFavouriteSportsKeys;
+
+ private List _favouriteCities;
+
+ private List _prioritisedFavouriteCartoonCharacters;
+ private List _prioritisedFavouriteCars;
+ private List _prioritisedFavouriteCountries;
+
+
+
+ // Cartoon Characters
+ public Map getDefaultFavouriteCartoonCharacters() {
+ Map m = new LinkedHashMap();
+ m.put("heMan", "He-Man");
+ m.put("popeye", "Popeye");
+ m.put("mockeyMouse", "Mickey Mouse");
+ return m;
+ }
+
+ public Map getDefaultNotFavouriteCartoonCharacters() {
+ Map m = new LinkedHashMap();
+ m.put("donaldDuck", "Donald Duck");
+ m.put("atomicAnt", "Atomic Ant");
+ m.put("pinkPainter", "Pink Painter");
+ return m;
+ }
+
+ public List getFavouriteCartoonCharacters() {
+ return _favouriteCartoonCharactersKeys;
+ }
+
+ public void setFavouriteCartoonCharacters(List favouriteCartoonCharacters) {
+ _favouriteCartoonCharactersKeys = favouriteCartoonCharacters;
+ }
+
+ public List getNotFavouriteCartoonCharacters() {
+ return _notFavouriteCartoonCharactersKeys;
+ }
+
+ public void setNotFavouriteCartoonCharacters(List notFavouriteCartoonCharacters) {
+ _notFavouriteCartoonCharactersKeys = notFavouriteCartoonCharacters;
+ }
+
+
+
+
+
+ // Cars
+ public Map getDefaultFavouriteCars() {
+ Map m = new LinkedHashMap();
+ m.put("alfaRomeo", "Alfa Romeo");
+ m.put("Toyota", "Toyota");
+ m.put("Mitsubitshi", "Mitsubitshi");
+ return m;
+ }
+
+ public Map getDefaultNotFavouriteCars() {
+ Map m = new LinkedHashMap();
+ m.put("ford", "Ford");
+ m.put("landRover", "Land Rover");
+ m.put("mercedes", "Mercedes");
+ return m;
+ }
+
+ public List getFavouriteCars() {
+ return _favouriteCarsKeys;
+ }
+
+ public void setFavouriteCars(List favouriteCars) {
+ _favouriteCarsKeys = favouriteCars;
+ }
+
+ public List getNotFavouriteCars() {
+ return _notFavouriteCarsKeys;
+ }
+
+ public void setNotFavouriteCars(List notFavouriteCars) {
+ _notFavouriteCarsKeys = notFavouriteCars;
+ }
+
+
+
+ // Motorcycles
+ public Map getDefaultFavouriteMotorcycles() {
+ Map m = new LinkedHashMap();
+ m.put("honda", "Honda");
+ m.put("yamaha", "Yamaha");
+ m.put("Aprillia", "Aprillia");
+ return m;
+ }
+
+ public Map getDefaultNotFavouriteMotorcycles() {
+ Map m = new LinkedHashMap();
+ m.put("cagiva", "Cagiva");
+ m.put("harleyDavidson", "Harley Davidson");
+ m.put("suzuki", "Suzuki");
+ return m;
+ }
+
+ public List getFavouriteMotorcycles() {
+ return _favouriteMotorcyclesKeys;
+ }
+
+ public void setFavouriteMotorcycles(List favouriteMotorcycles) {
+ _favouriteMotorcyclesKeys = favouriteMotorcycles;
+ }
+
+ public List getNotFavouriteMotorcycles() {
+ return _notFavouriteMotorcyclesKeys;
+ }
+
+ public void setNotFavouriteMotorcycles(List notFavouriteMotorcycles) {
+ _notFavouriteMotorcyclesKeys = notFavouriteMotorcycles;
+ }
+
+
+
+ // Countries
+ public Map getDefaultFavouriteCountries() {
+ Map m = new LinkedHashMap();
+ m.put("england", "England");
+ m.put("america", "America");
+ m.put("brazil", "Brazil");
+ return m;
+ }
+
+ public Map getDefaultNotFavouriteCountries() {
+ Map m = new LinkedHashMap();
+ m.put("germany", "Germany");
+ m.put("china", "China");
+ m.put("russia", "Russia");
+ return m;
+ }
+
+ public List getFavouriteCountries() {
+ return _favouriteCountriesKeys;
+ }
+
+ public void setFavouriteCountries(List favouriteCountries) {
+ _favouriteCountriesKeys = favouriteCountries;
+ }
+
+ public List getNotFavouriteCountries() {
+ return _notFavouriteCountriesKeys;
+ }
+
+ public void setNotFavouriteCountries(List notFavouriteCountries) {
+ _notFavouriteCountriesKeys = notFavouriteCountries;
+ }
+
+ // Sports
+ public Map getDefaultNonFavoriteSports() {
+ Map m = new LinkedHashMap();
+ m.put("basketball", "Basketball");
+ m.put("football", "Football");
+ m.put("baseball", "Baseball");
+ return m;
+ }
+
+ public Map getDefaultFavoriteSports() {
+ return new LinkedHashMap();
+ }
+
+ public List getFavouriteSports() {
+ return _favouriteSportsKeys;
+ }
+
+ public void setFavouriteSports(List favouriteSportsKeys) {
+ this._favouriteSportsKeys = favouriteSportsKeys;
+ }
+
+ public List getNonFavouriteSports() {
+ return _nonFavouriteSportsKeys;
+ }
+
+ public void setNonFavouriteSports(List notFavouriteSportsKeys) {
+ this._nonFavouriteSportsKeys = notFavouriteSportsKeys;
+ }
+
+
+
+
+ public List getPrioritisedFavouriteCartoonCharacters() {
+ return _prioritisedFavouriteCartoonCharacters;
+ }
+ public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) {
+ _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters;
+ }
+
+ public List getPrioritisedFavouriteCars() {
+ return _prioritisedFavouriteCars;
+ }
+ public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) {
+ _prioritisedFavouriteCars = prioritisedFavouriteCars;
+ }
+
+
+ public List getPrioritisedFavouriteCountries() {
+ return _prioritisedFavouriteCountries;
+ }
+ public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) {
+ _prioritisedFavouriteCountries = prioritisedFavouriteCountries;
+ }
+
+
+
+ public Map getAvailableCities() {
+ Map map = new LinkedHashMap();
+ map.put("boston", "Boston");
+ map.put("new york", "New York");
+ map.put("london", "London");
+ map.put("rome", "Rome");
+ return map;
+ }
+
+ public List getDefaultFavouriteCities() {
+ List list = new ArrayList();
+ list.add("boston");
+ list.add("rome");
+ return list;
+ }
+
+ public List getFavouriteCities() {
+ return _favouriteCities;
+ }
+
+ public void setFavouriteCities(List favouriteCities) {
+ this._favouriteCities = favouriteCities;
+ }
+
+ // actions
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java
new file mode 100644
index 000000000..410a499c7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java
@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class LotsOfRichtexteditorAction extends ActionSupport {
+
+ public String description1;
+ public String description2 = "This is Description 2";
+ public String description3;
+ public String description4 = "This is Description 4";
+
+ public String getDescription1() {
+ return this.description1;
+ }
+ public void setDescription1(String description1) {
+ this.description1 = description1;
+ }
+
+
+ public String getDescription2() {
+ return this.description2;
+ }
+ public void setDescription2(String description2) {
+ this.description2 = description2;
+ }
+
+
+ public String getDescription3() {
+ return this.description3;
+ }
+ public void setDescription3(String description3) {
+ this.description3 = description3;
+ }
+
+
+
+
+ public String getDescription4() {
+ return this.description4;
+ }
+ public void setDescription4(String description4) {
+ this.description4 = description4;
+ }
+
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java
new file mode 100644
index 000000000..516f4314a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java
@@ -0,0 +1,135 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.ArrayList;
+
+/**
+ */
+public class MoreSelectsAction extends ActionSupport {
+
+
+ private List _prioritisedFavouriteCartoonCharacters;
+ private List _prioritisedFavouriteCars;
+ private List _prioritisedFavouriteCountries;
+ private List favouriteNumbers;
+
+
+ // Cartoon Characters
+ public Map getDefaultFavouriteCartoonCharacters() {
+ Map m = new LinkedHashMap();
+ m.put("heMan", "He-Man");
+ m.put("popeye", "Popeye");
+ m.put("mockeyMouse", "Mickey Mouse");
+ return m;
+ }
+
+
+ // Cars
+ public Map getDefaultFavouriteCars() {
+ Map m = new LinkedHashMap();
+ m.put("alfaRomeo", "Alfa Romeo");
+ m.put("Toyota", "Toyota");
+ m.put("Mitsubitshi", "Mitsubitshi");
+ return m;
+ }
+
+
+
+ // Countries
+ public Map getDefaultFavouriteCountries() {
+ Map m = new LinkedHashMap();
+ m.put("england", "England");
+ m.put("america", "America");
+ m.put("brazil", "Brazil");
+ return m;
+ }
+
+ public List getDefaultFavouriteNumbers() {
+ List list = new ArrayList();
+ list.add("Three");
+ list.add("Seven");
+ return list;
+ }
+
+
+
+ public List getPrioritisedFavouriteCartoonCharacters() {
+ return _prioritisedFavouriteCartoonCharacters;
+ }
+ public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) {
+ _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters;
+ }
+
+ public List getPrioritisedFavouriteCars() {
+ return _prioritisedFavouriteCars;
+ }
+ public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) {
+ _prioritisedFavouriteCars = prioritisedFavouriteCars;
+ }
+
+
+ public List getPrioritisedFavouriteCountries() {
+ return _prioritisedFavouriteCountries;
+ }
+ public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) {
+ _prioritisedFavouriteCountries = prioritisedFavouriteCountries;
+ }
+
+ public List getFavouriteNumbers() {
+ return favouriteNumbers;
+ }
+
+ public void setFavouriteNumbers(List favouriteNumbers) {
+ this.favouriteNumbers = favouriteNumbers;
+ }
+
+ public Map getAvailableCities() {
+ Map map = new LinkedHashMap();
+ map.put("boston", "Boston");
+ map.put("new york", "New York");
+ map.put("london", "London");
+ map.put("rome", "Rome");
+ return map;
+ }
+
+ public List getDefaultFavouriteCities() {
+ List list = new ArrayList();
+ list.add("boston");
+ list.add("rome");
+ return list;
+ }
+
+ // actions
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java
new file mode 100644
index 000000000..fcbe56d0a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import org.apache.struts2.showcase.ajax.tree.Category;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+// START SNIPPET: treeExampleDynamicJavaShow
+
+public class ShowDynamicTreeAction extends ActionSupport {
+
+ public Category getTreeRootNode() {
+ return Category.getById(1);
+ }
+}
+
+// END SNIPPET: treeExampleDynamicJavaShow
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java
new file mode 100644
index 000000000..95fa0dded
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java
@@ -0,0 +1,322 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.struts2.ServletActionContext;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.Validateable;
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ */
+public class UITagExample extends ActionSupport implements Validateable {
+
+ private static final long serialVersionUID = -94044809860988047L;
+
+
+ String name;
+ Date birthday;
+ String bio;
+ String favouriteColor;
+ 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;
+
+ public UITagExample() {
+ 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);
+ }
+
+
+
+ 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() {
+ ValueStack stack = ServletActionContext.getValueStack(ServletActionContext.getRequest());
+ Object vehicalType = stack.findValue("top");
+ if (vehicalType != null && vehicalType instanceof VehicalType) {
+ List l = (List) vehicalSpecificMap.get(vehicalType);
+ return l;
+ }
+ return Collections.EMPTY_LIST;
+ }
+
+ public List getFavouriteLanguages() {
+ return favouriteLanguages;
+ }
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ 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 getFavouriteColor() {
+ return favouriteColor;
+ }
+
+ public void setFavouriteColor(String favoriteColor) {
+ this.favouriteColor = 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 File getPicture() {
+ return this.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;
+ }
+
+
+
+ public String doSubmit() {
+ return SUCCESS;
+ }
+
+
+
+ // === inner class
+ 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_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java
new file mode 100644
index 000000000..0e53d3832
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java
@@ -0,0 +1,97 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.action;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import org.apache.log4j.Logger;
+import org.apache.struts2.showcase.dao.Dao;
+import org.apache.struts2.showcase.model.IdEntity;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * AbstractCRUDAction.
+ *
+ */
+
+public abstract class AbstractCRUDAction extends ActionSupport {
+
+ private static final Logger log = Logger.getLogger(AbstractCRUDAction.class);
+
+ private Collection availableItems;
+ private String[] toDelete;
+
+ protected abstract Dao getDao();
+
+
+ public Collection getAvailableItems() {
+ return availableItems;
+ }
+
+ public String[] getToDelete() {
+ return toDelete;
+ }
+
+ public void setToDelete(String[] toDelete) {
+ this.toDelete = toDelete;
+ }
+
+ public String list() throws Exception {
+ this.availableItems = getDao().findAll();
+ if (log.isDebugEnabled()) {
+ log.debug("AbstractCRUDAction - [list]: " + (availableItems !=null?""+availableItems.size():"no") + " items found");
+ }
+ return execute();
+ }
+
+ public String delete() throws Exception {
+ if (toDelete != null) {
+ int count=0;
+ for (int i = 0, j=toDelete.length; i < j; i++) {
+ count = count + getDao().delete(toDelete[i]);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("AbstractCRUDAction - [delete]: " + count + " items deleted.");
+ }
+ }
+ return SUCCESS;
+ }
+
+ /**
+ * Utility method for fetching already persistent object from storage for usage in params-prepare-params cycle.
+ *
+ * @param tryId The id to try to get persistent object for
+ * @param tryObject The object, induced by first params invocation, possibly containing id to try to get persistent
+ * object for
+ * @return The persistent object, if found. null otherwise.
+ */
+ protected IdEntity fetch(Serializable tryId, IdEntity tryObject) {
+ IdEntity result = null;
+ if (tryId != null) {
+ result = getDao().get(tryId);
+ } else if (tryObject != null) {
+ result = getDao().get(tryObject.getId());
+ }
+ return result;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java
new file mode 100644
index 000000000..8af63fa23
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java
@@ -0,0 +1,126 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.action;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.apache.struts2.showcase.application.TestDataProvider;
+import org.apache.struts2.showcase.dao.Dao;
+import org.apache.struts2.showcase.dao.EmployeeDao;
+import org.apache.struts2.showcase.model.Employee;
+import org.apache.struts2.showcase.model.Skill;
+
+import com.opensymphony.xwork2.Preparable;
+
+/**
+ * JsfEmployeeAction.
+ */
+
+public class EmployeeAction extends AbstractCRUDAction implements Preparable {
+
+ private static final long serialVersionUID = 7047317819789938957L;
+
+ private static final Logger log = Logger.getLogger(EmployeeAction.class);
+
+ private Long empId;
+ protected EmployeeDao employeeDao;
+ private Employee currentEmployee;
+ private List selectedSkills;
+
+ public Long getEmpId() {
+ return empId;
+ }
+
+ public void setEmpId(Long empId) {
+ this.empId = empId;
+ }
+
+ public Employee getCurrentEmployee() {
+ return currentEmployee;
+ }
+
+ public void setCurrentEmployee(Employee currentEmployee) {
+ this.currentEmployee = currentEmployee;
+ }
+
+ public String[] getAvailablePositions() {
+ return TestDataProvider.POSITIONS;
+ }
+
+ public List getAvailableLevels() {
+ return Arrays.asList(TestDataProvider.LEVELS);
+ }
+
+ public List getSelectedSkills() {
+ return selectedSkills;
+ }
+
+ public void setSelectedSkills(List selectedSkills) {
+ this.selectedSkills = selectedSkills;
+ }
+
+ protected Dao getDao() {
+ return employeeDao;
+ }
+
+ public void setEmployeeDao(EmployeeDao employeeDao) {
+ if (log.isDebugEnabled()) {
+ log.debug("JsfEmployeeAction - [setEmployeeDao]: employeeDao injected.");
+ }
+ this.employeeDao = employeeDao;
+ }
+
+ /**
+ * This method is called to allow the action to prepare itself.
+ *
+ * @throws Exception thrown if a system level exception occurs.
+ */
+ public void prepare() throws Exception {
+ Employee preFetched = (Employee) fetch(getEmpId(), getCurrentEmployee());
+ if (preFetched != null) {
+ setCurrentEmployee(preFetched);
+ }
+ }
+
+ public String execute() throws Exception {
+ if (getCurrentEmployee() != null && getCurrentEmployee().getOtherSkills() != null) {
+ setSelectedSkills(new ArrayList());
+ Iterator it = getCurrentEmployee().getOtherSkills().iterator();
+ while (it.hasNext()) {
+ getSelectedSkills().add(((Skill) it.next()).getName());
+ }
+ }
+ return super.execute();
+ }
+
+ public String save() throws Exception {
+ if (getCurrentEmployee() != null) {
+ setEmpId((Long) employeeDao.merge(getCurrentEmployee()));
+ employeeDao.setSkills(getEmpId(), getSelectedSkills());
+ }
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java
new file mode 100644
index 000000000..96d10fc3d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java
@@ -0,0 +1,89 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.action;
+
+import org.apache.log4j.Logger;
+import org.apache.struts2.showcase.dao.Dao;
+import org.apache.struts2.showcase.dao.SkillDao;
+import org.apache.struts2.showcase.model.Skill;
+
+import com.opensymphony.xwork2.Preparable;
+
+/**
+ * SkillAction.
+ *
+ */
+
+public class SkillAction extends AbstractCRUDAction implements Preparable {
+
+ private static final Logger log = Logger.getLogger(SkillAction.class);
+
+ private String skillName;
+ protected SkillDao skillDao;
+ private Skill currentSkill;
+
+ public String getSkillName() {
+ return skillName;
+ }
+
+ public void setSkillName(String skillName) {
+ this.skillName = skillName;
+ }
+
+ protected Dao getDao() {
+ return skillDao;
+ }
+
+ public void setSkillDao(SkillDao skillDao) {
+ if (log.isDebugEnabled()) {
+ log.debug("SkillAction - [setSkillDao]: skillDao injected.");
+ }
+ this.skillDao = skillDao;
+ }
+
+ public Skill getCurrentSkill() {
+ return currentSkill;
+ }
+
+ public void setCurrentSkill(Skill currentSkill) {
+ this.currentSkill = currentSkill;
+ }
+
+ /**
+ * This method is called to allow the action to prepare itself.
+ *
+ * @throws Exception thrown if a system level exception occurs.
+ */
+ public void prepare() throws Exception {
+ Skill preFetched = (Skill) fetch(getSkillName(), getCurrentSkill());
+ if (preFetched != null) {
+ setCurrentSkill(preFetched);
+ }
+ }
+
+ public String save() throws Exception {
+ if (getCurrentSkill() != null) {
+ setSkillName((String) skillDao.merge(getCurrentSkill()));
+ }
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java
new file mode 100644
index 000000000..26fb309da
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.actionchaining;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class ActionChain1 extends ActionSupport {
+
+ private static final long serialVersionUID = -6811701750042275153L;
+
+ private String actionChain1Property1 = "Property Set In Action Chain 1";
+
+ public String getActionChain1Property1() {
+ return actionChain1Property1;
+ }
+ public void setActionChain1Property1(String actionChain1Property1) {
+ this.actionChain1Property1 = actionChain1Property1;
+ }
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java
new file mode 100644
index 000000000..603d19fd9
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.actionchaining;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class ActionChain2 extends ActionSupport {
+
+ private static final long serialVersionUID = 3951745956044674809L;
+
+ private String actionChain1Property1;
+ private String actionChain2Property1 = "Property Set in Action Chain 2";
+
+
+ public String getActionChain1Property1() {
+ return actionChain1Property1;
+ }
+ public void setActionChain1Property1(String actionChain1Property1) {
+ this.actionChain1Property1 = actionChain1Property1;
+ }
+
+
+
+ public String getActionChain2Property1() {
+ return actionChain2Property1;
+ }
+ public void setActionChain2Property1(String actionChain2Property1) {
+ this.actionChain2Property1 = actionChain2Property1;
+ }
+
+
+
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java
new file mode 100644
index 000000000..f2ec60cc9
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.actionchaining;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class ActionChain3 extends ActionSupport {
+
+ private static final long serialVersionUID = -1456568865075250621L;
+
+ private String actionChain1Property1;
+ private String actionChain2Property1;
+ private String actionChain3Property1 = "Property set in Action Chain 3";
+
+
+ public String getActionChain1Property1() {
+ return actionChain1Property1;
+ }
+ public void setActionChain1Property1(String actionChain1Property1) {
+ this.actionChain1Property1 = actionChain1Property1;
+ }
+
+
+
+ public String getActionChain2Property1() {
+ return actionChain2Property1;
+ }
+ public void setActionChain2Property1(String actionChain2Property1) {
+ this.actionChain2Property1 = actionChain2Property1;
+ }
+
+
+
+ public String getActionChain3Property1() {
+ return actionChain3Property1;
+ }
+ public void setActionChain3Property1(String actionChain3Property1) {
+ this.actionChain3Property1 = actionChain3Property1;
+ }
+
+
+
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java
new file mode 100644
index 000000000..c078ca74c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax;
+
+import com.opensymphony.xwork2.Action;
+
+import java.io.Serializable;
+
+
+/**
+ */
+public class AjaxTestAction implements Action, Serializable {
+
+ private static int counter = 0;
+ private String data;
+
+ public long getServerTime() {
+ return System.currentTimeMillis();
+ }
+
+ public int getCount() {
+ return ++counter;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java
new file mode 100644
index 000000000..3c149fc0b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java
@@ -0,0 +1,39 @@
+package org.apache.struts2.showcase.ajax;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class AutocompleterExampleAction extends ActionSupport {
+ private String select;
+ private List options = new ArrayList();
+
+ private static final long serialVersionUID = -8481638176160014396L;
+
+ public String execute() throws Exception {
+ if ("fruits".equals(select)) {
+ options.add("apple");
+ options.add("banana");
+ options.add("grape");
+ options.add("pear");
+ } else if ("colors".equals(select)) {
+ options.add("red");
+ options.add("green");
+ options.add("blue");
+ }
+ return SUCCESS;
+ }
+
+ public String getSelect() {
+ return select;
+ }
+
+ public void setSelect(String select) {
+ this.select = select;
+ }
+
+ public List getOptions() {
+ return options;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java
new file mode 100644
index 000000000..6ff756de9
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java
@@ -0,0 +1,75 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class Example4ShowPanelAction extends ActionSupport {
+
+ private String name;
+ private String gender;
+
+ private static final long serialVersionUID = 7751976335066456596L;
+
+ public String panel1() throws Exception {
+ return SUCCESS;
+ }
+
+ public String panel2() throws Exception {
+ return SUCCESS;
+ }
+
+ public String panel3() throws Exception {
+ return SUCCESS;
+ }
+
+ public String getGender() {
+ return gender;
+ }
+
+ public void setGender(String gender) {
+ this.gender = gender;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTodayDate() {
+ SimpleDateFormat sdf = new SimpleDateFormat("dd-MMMM-yyyy");
+ return sdf.format(new Date());
+ }
+
+ public String getTodayTime() {
+ SimpleDateFormat sdf = new SimpleDateFormat("kk:mm:ss");
+ return sdf.format(new Date());
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java
new file mode 100644
index 000000000..4fcc516eb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class Example5Action extends ActionSupport {
+
+ private static final long serialVersionUID = 2111967621952300611L;
+
+ private String name;
+ private Integer age;
+
+
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+
+ public Integer getAge() { return age; }
+ public void setAge(Integer age) { this.age = age; }
+
+ @Override
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java
new file mode 100644
index 000000000..b3a9859b0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java
@@ -0,0 +1,104 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax.tree;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ */
+public class Category {
+ private static Map catMap = new HashMap();
+
+ static {
+ new Category(1, "Root",
+ new Category(2, "Java",
+ new Category(3, "Web Frameworks",
+ new Category(4, "Struts"),
+ new Category(7, "Stripes"),
+ new Category(8, "Rife")),
+ new Category(9, "Persistence",
+ new Category(10, "iBatis"),
+ new Category(11, "Hibernate"),
+ new Category(12, "JDO"),
+ new Category(13, "JDBC"))),
+ new Category(14, "JavaScript",
+ new Category(15, "Dojo"),
+ new Category(16, "Prototype"),
+ new Category(17, "Scriptaculous"),
+ new Category(18, "OpenRico"),
+ new Category(19, "DWR")));
+ }
+
+ public static Category getById(long id) {
+ return catMap.get(id);
+ }
+
+ private long id;
+ private String name;
+ private List children;
+ private boolean toggle;
+
+ public Category(long id, String name, Category... children) {
+ this.id = id;
+ this.name = name;
+ this.children = new ArrayList();
+ for (Category child : children) {
+ this.children.add(child);
+ }
+
+ catMap.put(id, this);
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getChildren() {
+ return children;
+ }
+
+ public void setChildren(List children) {
+ this.children = children;
+ }
+
+ public void toggle() {
+ toggle = !toggle;
+ }
+
+ public boolean isToggle() {
+ return toggle;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java
new file mode 100644
index 000000000..69f6bd064
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax.tree;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class GetCategory extends ActionSupport {
+ private long catId;
+ private Category category;
+
+ public String execute() throws Exception {
+ if (catId < 1) {
+ // force the root
+ catId = 1;
+ }
+
+ category = Category.getById(catId);
+
+ return SUCCESS;
+ }
+
+ public void setCatId(long catId) {
+ this.catId = catId;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java
new file mode 100644
index 000000000..165b22266
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.ajax.tree;
+
+
+/**
+ */
+public class Toggle extends GetCategory {
+ public String execute() throws Exception {
+ super.execute();
+
+ getCategory().toggle();
+
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java
new file mode 100644
index 000000000..f1f2d7093
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java
@@ -0,0 +1,142 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.application;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.struts2.showcase.exception.CreateException;
+import org.apache.struts2.showcase.exception.DuplicateKeyException;
+import org.apache.struts2.showcase.exception.StorageException;
+import org.apache.struts2.showcase.exception.UpdateException;
+import org.apache.struts2.showcase.model.IdEntity;
+
+/**
+ * MemoryStorage.
+ * Very simple in-memory persistence emulation.
+ *
+ */
+
+public class MemoryStorage implements Storage {
+
+ private static final long serialVersionUID = 8611213748834904125L;
+
+
+ private Map memory = new HashMap();
+
+ private Map getEntityMap ( Class entityClass ) {
+ if (entityClass != null) {
+ Map tryMap = (Map) memory.get(entityClass);
+ if (tryMap == null) {
+ synchronized(memory) {
+ tryMap = new HashMap();
+ memory.put(entityClass, tryMap);
+ }
+ }
+ return tryMap;
+ } else {
+ return null;
+ }
+ }
+
+ private IdEntity intStore( Class entityClass, IdEntity object ) {
+ getEntityMap(entityClass).put(object.getId(), object);
+ return object;
+ }
+
+ public IdEntity get( Class entityClass, Serializable id ) {
+ if (entityClass != null && id != null) {
+ return (IdEntity) getEntityMap(entityClass).get(id);
+ } else {
+ return null;
+ }
+ }
+
+ public Serializable create ( IdEntity object ) throws CreateException {
+ if (object == null) {
+ throw new CreateException("Either given class or object was null");
+ }
+ if (object.getId() == null) {
+ throw new CreateException("Cannot store object with null id");
+ }
+ if (get(object.getClass(), object.getId()) != null) {
+ throw new DuplicateKeyException("Object with this id already exists.");
+ }
+ return intStore(object.getClass(), object).getId();
+ }
+
+ public IdEntity update ( IdEntity object ) throws UpdateException {
+ if (object == null) {
+ throw new UpdateException("Cannot update null object.");
+ }
+ if ( get(object.getClass(), object.getId())==null ) {
+ throw new UpdateException("Object to update not found.");
+ }
+ return intStore(object.getClass(), object);
+ }
+
+ public Serializable merge ( IdEntity object ) throws StorageException {
+ if (object == null) {
+ throw new StorageException("Cannot merge null object");
+ }
+ if (object.getId() == null || get(object.getClass(), object.getId())==null) {
+ return create(object);
+ } else {
+ return update(object).getId();
+ }
+ }
+
+ public int delete( Class entityClass, Serializable id ) throws CreateException {
+ try {
+ if (get(entityClass, id) != null) {
+ getEntityMap(entityClass).remove(id);
+ return 1;
+ } else {
+ return 0;
+ }
+ } catch (Exception e) {
+ throw new CreateException(e);
+ }
+ }
+
+ public int delete( IdEntity object ) throws CreateException {
+ if (object == null) {
+ throw new CreateException("Cannot delete null object");
+ }
+ return delete(object.getClass(), object.getId());
+ }
+
+ public Collection findAll( Class entityClass ) {
+ if (entityClass != null) {
+ return getEntityMap(entityClass).values();
+ } else {
+ return new ArrayList();
+ }
+ }
+
+ public void reset() {
+ this.memory = new HashMap();
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java
new file mode 100644
index 000000000..74d81e3b4
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.application;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import org.apache.struts2.showcase.exception.CreateException;
+import org.apache.struts2.showcase.exception.StorageException;
+import org.apache.struts2.showcase.exception.UpdateException;
+import org.apache.struts2.showcase.model.IdEntity;
+
+/**
+ * Storage. Interface.
+ *
+ */
+
+public interface Storage extends Serializable {
+ IdEntity get( Class entityClass, Serializable id );
+
+ Serializable create ( IdEntity object ) throws CreateException;
+
+ IdEntity update ( IdEntity object ) throws UpdateException;
+
+ Serializable merge ( IdEntity object ) throws StorageException;
+
+ int delete( Class entityClass, Serializable id ) throws CreateException;
+
+ int delete( IdEntity object ) throws CreateException;
+
+ Collection findAll( Class entityClass );
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java
new file mode 100644
index 000000000..0cd0056df
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java
@@ -0,0 +1,118 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.application;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Date;
+
+import org.apache.log4j.Logger;
+import org.apache.struts2.showcase.dao.EmployeeDao;
+import org.apache.struts2.showcase.dao.SkillDao;
+import org.apache.struts2.showcase.exception.StorageException;
+import org.apache.struts2.showcase.model.Employee;
+import org.apache.struts2.showcase.model.Skill;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * TestDataProvider.
+ *
+ */
+
+public class TestDataProvider implements Serializable, InitializingBean {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger log = Logger.getLogger(TestDataProvider.class);
+
+ public static final String[] POSITIONS = {
+ "Developer",
+ "System Architect",
+ "Sales Manager",
+ "CEO"
+ };
+
+ public static final String[] LEVELS = {
+ "Junior",
+ "Senior",
+ "Master"
+ };
+
+ private static final Skill[] TEST_SKILLS = {
+ new Skill("WW-SEN", "Struts Senior Developer"),
+ new Skill("WW-JUN", "Struts Junior Developer"),
+ new Skill("SPRING-DEV", "Spring Developer")
+ };
+
+ public static final Employee[] TEST_EMPLOYEES = {
+ new Employee(new Long(1), "Alan", "Smithee", new Date(), new Float(2000f), true, POSITIONS[0],
+ TEST_SKILLS[0], null, "alan", LEVELS[0], "Nice guy"),
+ new Employee(new Long(2), "Robert", "Robson", new Date(), new Float(10000f), false, POSITIONS[1],
+ TEST_SKILLS[1], Arrays.asList(TEST_SKILLS).subList(1,TEST_SKILLS.length), "rob", LEVELS[1], "Smart guy")
+ };
+
+ private SkillDao skillDao;
+ private EmployeeDao employeeDao;
+
+ public void setSkillDao(SkillDao skillDao) {
+ this.skillDao = skillDao;
+ }
+
+ public void setEmployeeDao(EmployeeDao employeeDao) {
+ this.employeeDao = employeeDao;
+ }
+
+ protected void addTestSkills() {
+ try {
+ for (int i = 0, j = TEST_SKILLS.length; i < j; i++) {
+ skillDao.merge(TEST_SKILLS[i]);
+ }
+ if (log.isInfoEnabled()) {
+ log.info("TestDataProvider - [addTestSkills]: Added test skill data.");
+ }
+ } catch (StorageException e) {
+ log.error("TestDataProvider - [addTestSkills]: Exception catched: " + e.getMessage());
+ }
+ }
+
+ protected void addTestEmployees() {
+ try {
+ for (int i = 0, j = TEST_EMPLOYEES.length; i < j; i++) {
+ employeeDao.merge(TEST_EMPLOYEES[i]);
+ }
+ if (log.isInfoEnabled()) {
+ log.info("TestDataProvider - [addTestEmployees]: Added test employee data.");
+ }
+ } catch (StorageException e) {
+ log.error("TestDataProvider - [addTestEmployees]: Exception catched: " + e.getMessage());
+ }
+ }
+
+ protected void addTestData() {
+ addTestSkills();
+ addTestEmployees();
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ addTestData();
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java
new file mode 100644
index 000000000..281f67347
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.dispatcher.SessionMap;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+
+public class ChatAuthenticationInterceptor implements Interceptor {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Log _log = LogFactory.getLog(ChatAuthenticationInterceptor.class);
+
+ public static final String USER_SESSION_KEY = "chatUserSessionKey";
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation invocation) throws Exception {
+
+ _log.debug("Authenticating chat user");
+
+ SessionMap session = (SessionMap) ActionContext.getContext().get(ActionContext.SESSION);
+ User user = (User) session.get(USER_SESSION_KEY);
+
+ if (user == null) {
+ return Action.LOGIN;
+ }
+ return invocation.invoke();
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java
new file mode 100644
index 000000000..50b5e9b81
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+public class ChatException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public enum ErrorType {
+ ROOM_ALREADY_EXISTS,
+ USER_ALREADY_EXISTS,
+ NO_SUCH_ROOM_EXISTS
+ }
+
+ public ChatException(String description, ErrorType type) {
+ super(description);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java
new file mode 100644
index 000000000..4e9afbda0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+
+/**
+ * Authenticate showcase chat example, make sure everyone have a username.
+ */
+public class ChatInterceptor implements Interceptor {
+
+ private static final Log _log = LogFactory.getLog(ChatInterceptor.class);
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String CHAT_USER_SESSION_KEY = "ChatUserSessionKey";
+
+ public void destroy() {
+ }
+
+ public void init() {
+ }
+
+ public String intercept(ActionInvocation invocation) throws Exception {
+ HttpSession session = (HttpSession) ActionContext.getContext().get(ActionContext.SESSION);
+ User chatUser = (User) session.getAttribute(CHAT_USER_SESSION_KEY);
+ if (chatUser == null) {
+ _log.debug("Chat user not logged in");
+ return Action.LOGIN;
+ }
+ return invocation.invoke();
+ }
+}
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java
new file mode 100644
index 000000000..570d54523
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class ChatLoginAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+ private Map session;
+
+ private String name;
+
+ public ChatLoginAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ public String execute() throws Exception {
+ try {
+ chatService.login(new User(name));
+ session.put(ChatAuthenticationInterceptor.USER_SESSION_KEY, new User(name));
+ }
+ catch(ChatException e) {
+ e.printStackTrace();
+ addActionError(e.getMessage());
+ return INPUT;
+ }
+ return SUCCESS;
+ }
+
+
+ // === SessionAware ===
+ public void setSession(Map session) {
+ this.session = session;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java
new file mode 100644
index 000000000..c4a4bcd5e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class ChatLogoutAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+
+ private Map session;
+
+
+ public ChatLogoutAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+
+ User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY);
+ if (user != null) {
+ chatService.logout(user.getName());
+ session.remove(ChatAuthenticationInterceptor.USER_SESSION_KEY);
+ }
+
+ return SUCCESS;
+ }
+
+
+ // === SessionAware ===
+ public void setSession(Map session) {
+ this.session = session;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java
new file mode 100644
index 000000000..3426eec0e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Date;
+
+public class ChatMessage {
+
+ private Date creationDate;
+ private String message;
+ private User creator;
+
+ public ChatMessage(String message, User creator) {
+ assert(message != null);
+ assert(creator != null);
+
+ this.creationDate = new Date(System.currentTimeMillis());
+ this.message = message;
+ this.creator = creator;
+ }
+
+ public Date getCreationDate() {
+ return creationDate;
+ }
+ public User getCreator() {
+ return creator;
+ }
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java
new file mode 100644
index 000000000..907f77e00
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.List;
+
+public interface ChatService {
+ List getAvailableUsers();
+ void login(User user);
+ void logout(String name);
+
+ List getAvailableRooms();
+ void addRoom(Room room);
+ void enterRoom(User user, String roomName);
+ void exitRoom(String userName, String roomName);
+ List getMessagesInRoom(String roomName);
+ void sendMessageToRoom(String roomName, User user, String message);
+ List getUsersAvailableInRoom(String roomName);
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java
new file mode 100644
index 000000000..0cd783d7d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java
@@ -0,0 +1,115 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ChatServiceImpl implements ChatService {
+
+ private Map availableUsers = new LinkedHashMap();
+ private Map availableRooms = new LinkedHashMap();
+
+
+ public List getAvailableUsers() {
+ return new ArrayList(availableUsers.values());
+ }
+
+ public List getAvailableRooms() {
+ return new ArrayList(availableRooms.values());
+ }
+
+ public void addRoom(Room room) {
+ if (availableRooms.containsKey(room.getName())) {
+ throw new ChatException("room ["+room.getName()+"] is already available", ChatException.ErrorType.valueOf("ROOM_ALREADY_EXISTS"));
+ }
+ availableRooms.put(room.getName(), room);
+ }
+
+ public void login(User user) {
+ assert(user != null);
+ if (availableUsers.containsKey(user.getName())) {
+ throw new ChatException("User ["+user.getName()+"] already exists", ChatException.ErrorType.valueOf("USER_ALREADY_EXISTS"));
+ }
+ availableUsers.put(user.getName(), user);
+ }
+
+ public void logout(String name) {
+ assert(name != null);
+ assert(name.trim().length() > 0);
+ availableUsers.remove(name);
+ for (Room room : availableRooms.values()) {
+ if (room.hasMember(name)) {
+ room.memberExit(name);
+ }
+ }
+ }
+
+ public void exitRoom(String userName, String roomName) {
+ assert(roomName != null);
+ assert(roomName.trim().length()> 0);
+
+ if (availableRooms.containsKey(roomName)) {
+ Room room = availableRooms.get(roomName);
+ room.memberExit(userName);
+ }
+ }
+
+ public void enterRoom(User user, String roomName) {
+ assert(roomName != null);
+ assert(roomName.trim().length() > 0);
+ if (! availableRooms.containsKey(roomName)) {
+ throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS);
+ }
+ Room room = availableRooms.get(roomName);
+ room.memberEnter(user);
+ }
+
+ public List getMessagesInRoom(String roomName) {
+ assert(roomName != null);
+ assert(roomName.trim().length() > 0);
+ if (! availableRooms.containsKey(roomName)) {
+ throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS);
+ }
+ Room room = availableRooms.get(roomName);
+ return room.getChatMessages();
+ }
+
+ public void sendMessageToRoom(String roomName, User user, String message) {
+ assert(roomName != null);
+ if (! availableRooms.containsKey(roomName)) {
+ throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS);
+ }
+ Room room = availableRooms.get(roomName);
+ room.addMessage(new ChatMessage(message, user));
+ }
+
+ public List getUsersAvailableInRoom(String roomName) {
+ assert(roomName != null);
+ if (! availableRooms.containsKey(roomName)) {
+ throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS);
+ }
+ Room room = availableRooms.get(roomName);
+ return room.getMembers();
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java
new file mode 100644
index 000000000..0e6d430fe
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+public class ChatSessionListener implements HttpSessionListener {
+
+ private static final Log _log = LogFactory.getLog(ChatSessionListener.class);
+
+ public void sessionCreated(HttpSessionEvent event) {
+ }
+
+ public void sessionDestroyed(HttpSessionEvent event) {
+ HttpSession session = event.getSession();
+ WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());
+ if (context != null) {
+ User user = (User) session.getAttribute(ChatInterceptor.CHAT_USER_SESSION_KEY);
+ if (user != null) {
+ ChatService service = (ChatService) context.getBean("chatService");
+ service.logout(user.getName());
+
+ _log.info("session expired, logged user ["+user.getName()+"] out");
+ }
+ }
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java
new file mode 100644
index 000000000..39ad1fb4d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+public class Constants {
+ public static String UPDATE_FREQ = "30000";
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java
new file mode 100644
index 000000000..dcbf24096
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class CrudRoomAction extends ActionSupport {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+
+ private String name;
+ private String description;
+
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public CrudRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String create() throws Exception {
+ try {
+ chatService.addRoom(new Room(name, description));
+ }
+ catch(ChatException e) {
+ addActionError(e.getMessage());
+ }
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java
new file mode 100644
index 000000000..72b707813
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.util.StrutsTypeConverter;
+
+public class DateConverter extends StrutsTypeConverter {
+
+ private static final Log _log = LogFactory.getLog(DateConverter.class);
+
+ public Object convertFromString(Map context, String[] values, Class toClass) {
+
+ if (values.length > 0 && values[0] != null && values[0].trim().length() > 0) {
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ try {
+ return sdf.parse(values[0]);
+ }
+ catch(ParseException e) {
+ _log.error("error converting value ["+values[0]+"] to Date ", e);
+ }
+ }
+ return null;
+ }
+
+ public String convertToString(Map context, Object o) {
+
+ if (o instanceof Date) {
+ SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
+ return sdf.format((Date) o);
+ }
+ return "";
+ }
+}
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java
new file mode 100644
index 000000000..52e872258
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java
@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class EnterRoomAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+ private Map session;
+ private String roomName;
+
+ public String getRoomName() { return this.roomName; }
+ public void setRoomName(String roomName) { this.roomName = roomName; }
+
+ public EnterRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+
+ User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY);
+ try {
+ chatService.enterRoom(user, roomName);
+ }
+ catch(Exception e) {
+ addActionError(e.getMessage());
+ }
+ return SUCCESS;
+ }
+
+
+ // === SessionAware ===
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java
new file mode 100644
index 000000000..5d0990f04
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class ExitRoomAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 1L;
+
+ private String roomName;
+
+ private Map session;
+
+ public String getRoomName() { return roomName; }
+ public void setRoomName(String roomName) { this.roomName = roomName; }
+
+ private ChatService chatService;
+
+ public ExitRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+ User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY);
+ chatService.exitRoom(user.getName(), roomName);
+
+ return SUCCESS;
+ }
+
+ // === SessionAware ===
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java
new file mode 100644
index 000000000..ffb6e54e3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class MessagesAvailableInRoomAction extends ActionSupport {
+
+ private static final long serialVersionUID = 1L;
+
+ private String roomName;
+ private ChatService chatService;
+ private List messagesAvailableInRoom = new ArrayList();
+
+ public String getRoomName() { return this.roomName; }
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public List getMessagesAvailableInRoom() {
+ return messagesAvailableInRoom;
+ }
+
+ public MessagesAvailableInRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+ try {
+ messagesAvailableInRoom = chatService.getMessagesInRoom(roomName);
+ }
+ catch(ChatException e) {
+ addActionError(e.getMessage());
+ }
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java
new file mode 100644
index 000000000..1ac856ef7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java
@@ -0,0 +1,101 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Room {
+
+ private static final int MAX_CHAT_MESSAGES = 10;
+
+ private String name;
+ private String description;
+ private Date creationDate;
+
+ private List messages = new ArrayList();
+
+ private Map members = new LinkedHashMap();
+
+ public Room(String name, String description) {
+ this.name = name;
+ this.description = description;
+ this.creationDate = new Date(System.currentTimeMillis());
+ }
+
+
+ // properties
+ public Date getCreationDate() {
+ return creationDate;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+
+ // (behaviour) members
+ public List getMembers() {
+ return new ArrayList(members.values());
+ }
+ public User findMember(String name) {
+ assert(name != null);
+ return members.get(name);
+ }
+ public boolean hasMember(String name) {
+ assert(name != null);
+ return members.containsKey(name);
+ }
+ public void memberEnter(User member) {
+ assert(member != null);
+ if (! hasMember(member.getName())) {
+ members.put(member.getName(), member);
+ }
+ }
+
+ public void memberExit(String memberName) {
+ assert(memberName != null);
+ assert(memberName.trim().length() > 0);
+ members.remove(memberName);
+ }
+
+
+ // (behaviour) chat messags
+ public void addMessage(ChatMessage chatMessage) {
+ if (messages.size() > MAX_CHAT_MESSAGES) {
+ // messages.remove(messages.size() - 1);
+ messages.remove(0);
+ }
+ messages.add(chatMessage);
+ }
+
+ public List getChatMessages() {
+ return new ArrayList(messages);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java
new file mode 100644
index 000000000..25084d4ee
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class RoomsAvailableAction extends ActionSupport {
+
+ private static final long serialVersionUID = 1L;
+
+ private List availableRooms = new ArrayList();
+
+ private ChatService chatService;
+
+ public RoomsAvailableAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+ availableRooms = chatService.getAvailableRooms();
+ return SUCCESS;
+ }
+
+ public List getAvailableRooms() {
+ return availableRooms;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java
new file mode 100644
index 000000000..a24e6c6c1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class SendMessageToRoomAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+
+ private String roomName;
+ private String message;
+ private Map session;
+
+
+ public SendMessageToRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String getRoomName() { return this.roomName; }
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public String getMessage() { return this.message; }
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+
+ public String execute() throws Exception {
+ User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY);
+ try {
+ chatService.sendMessageToRoom(roomName, user, message);
+ }catch(ChatException e) {
+ addActionError(e.getMessage());
+ }
+ return SUCCESS;
+ }
+
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java
new file mode 100644
index 000000000..b649aca5d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Represends a user in the Chat example.
+ */
+public class User implements Serializable {
+
+ private static final long serialVersionUID = -1434958919516089297L;
+
+ private String name;
+ private Date creationDate;
+
+
+ public User(String name) {
+ this.name = name;
+ this.creationDate = new Date(System.currentTimeMillis());
+ }
+
+ public Date getCreationDate() {
+ return creationDate;
+ }
+ public String getName() {
+ return name;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java
new file mode 100644
index 000000000..eae9a8cfe
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class UsersAvailableAction extends ActionSupport {
+
+ private static final long serialVersionUID = 1L;
+
+ private List availableUsers = new ArrayList();
+ private ChatService chatService;
+
+ public UsersAvailableAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+ public String execute() throws Exception {
+
+ availableUsers = chatService.getAvailableUsers();
+
+ return SUCCESS;
+ }
+
+ public List getAvailableUsers() {
+ return availableUsers;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java
new file mode 100644
index 000000000..f56f4334c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.chat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class UsersAvailableInRoomAction extends ActionSupport {
+
+ private static final long serialVersionUID = 1L;
+
+ private ChatService chatService;
+ private List usersAvailableInRoom = new ArrayList();
+
+ private String roomName;
+
+ public UsersAvailableInRoomAction(ChatService chatService) {
+ this.chatService = chatService;
+ }
+
+
+ public String getRoomName() { return this.roomName; }
+ public void setRoomName(String roomName) {
+ this.roomName = roomName;
+ }
+
+ public List getUsersAvailableInRoom() {
+ return usersAvailableInRoom;
+ }
+
+ public String execute() throws Exception {
+ try {
+ usersAvailableInRoom = chatService.getUsersAvailableInRoom(roomName);
+ }
+ catch(ChatException e) {
+ addActionError(e.getMessage());
+ }
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java
new file mode 100644
index 000000000..371def7b6
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+
+/**
+ * @version $Date$ $Id$
+ */
+public class Address {
+
+ private String id;
+ private String address;
+
+ public String getId() { return id; }
+ public void setId(String id) { this.id = id; }
+
+ public String getAddress() { return address; }
+ public void setAddress(String address) { this.address = address; }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java
new file mode 100644
index 000000000..a0d20d903
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class AddressAction extends ActionSupport {
+
+ private Set addresses = new LinkedHashSet();
+
+ public Set getAddresses() { return addresses; }
+ public void setAddresses(Set addresses) { this.addresses = addresses; }
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ System.out.println(addresses);
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java
new file mode 100644
index 000000000..6efa44cf3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.struts2.util.StrutsTypeConverter;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class EnumTypeConverter extends StrutsTypeConverter {
+
+ @Override
+ public Object convertFromString(Map context, String[] values, Class toClass) {
+ List result = new ArrayList();
+ for (int a=0; a< values.length; a++) {
+ Enum e = Enum.valueOf(OperationsEnum.class, values[a]);
+ if (e != null)
+ result.add(e);
+ }
+ return result;
+ }
+
+ @Override
+ public String convertToString(Map context, Object o) {
+ List l = (List) o;
+ String result ="<";
+ for (Iterator i = l.iterator(); i.hasNext(); ) {
+ result = result + "["+ i.next() +"]";
+ }
+ result = result+">";
+ return result;
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java
new file mode 100644
index 000000000..e9a77988f
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public enum OperationsEnum {
+ ADD,
+ MINUS,
+ DIVIDE,
+ MULTIPLY,
+ REMAINDER;
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java
new file mode 100644
index 000000000..2769858a3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java
@@ -0,0 +1,56 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public class OperationsEnumAction extends ActionSupport {
+
+ private static final long serialVersionUID = -2229489704988870318L;
+
+ private List selectedOperations = new LinkedList();
+
+ public List getSelectedOperations() { return this.selectedOperations; }
+ public void setSelectedOperations(List selectedOperations) {
+ this.selectedOperations = selectedOperations;
+ }
+
+
+ public List getAvailableOperations() {
+ return Arrays.asList(OperationsEnum.values());
+ }
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java
new file mode 100644
index 000000000..ed63fd42c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+import java.io.Serializable;
+
+/**
+ *
+ */
+public class Person implements Serializable {
+ private String name;
+ private Integer age;
+
+ public void setName(String name) { this.name = name; }
+ public String getName() { return this.name; }
+
+ public void setAge(Integer age) { this.age = age; }
+ public Integer getAge() { return this.age; }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java
new file mode 100644
index 000000000..96ff77d40
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.conversion;
+
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class PersonAction extends ActionSupport {
+
+ private List persons;
+
+ public List getPersons() { return persons; }
+ public void setPersons(List persons) { this.persons = persons; }
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java
new file mode 100644
index 000000000..aae90e729
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java
@@ -0,0 +1,77 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.dao;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import org.apache.struts2.showcase.application.Storage;
+import org.apache.struts2.showcase.exception.CreateException;
+import org.apache.struts2.showcase.exception.StorageException;
+import org.apache.struts2.showcase.exception.UpdateException;
+import org.apache.struts2.showcase.model.IdEntity;
+
+/**
+ * AbstractDao.
+ *
+ */
+
+public abstract class AbstractDao implements Serializable, Dao {
+
+ private Storage storage;
+
+ public Storage getStorage() {
+ return storage;
+ }
+
+ public void setStorage(Storage storage) {
+ this.storage = storage;
+ }
+
+ public IdEntity get(Serializable id) {
+ return getStorage().get(getFeaturedClass(), id);
+ }
+
+ public Serializable create(IdEntity object) throws CreateException {
+ return getStorage().create(object);
+ }
+
+ public IdEntity update(IdEntity object) throws UpdateException {
+ return getStorage().update(object);
+ }
+
+ public Serializable merge(IdEntity object) throws StorageException {
+ return getStorage().merge(object);
+ }
+
+ public int delete(Serializable id) throws CreateException {
+ return getStorage().delete(getFeaturedClass(), id);
+ }
+
+ public int delete(IdEntity object) throws CreateException {
+ return getStorage().delete(object);
+ }
+
+ public Collection findAll() {
+ return getStorage().findAll(getFeaturedClass());
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java
new file mode 100644
index 000000000..9a88319da
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.dao;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import org.apache.struts2.showcase.exception.CreateException;
+import org.apache.struts2.showcase.exception.StorageException;
+import org.apache.struts2.showcase.exception.UpdateException;
+import org.apache.struts2.showcase.model.IdEntity;
+
+/**
+ * Dao. Interface.
+ *
+ */
+
+public interface Dao {
+
+ Class getFeaturedClass();
+
+ IdEntity get(Serializable id);
+
+ Serializable create(IdEntity object) throws CreateException;
+
+ IdEntity update(IdEntity object) throws UpdateException;
+
+ Serializable merge(IdEntity object) throws StorageException;
+
+ int delete(Serializable id) throws CreateException;
+
+ int delete(IdEntity object) throws CreateException;
+
+ Collection findAll();
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java
new file mode 100644
index 000000000..ebec67348
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts2.showcase.model.Employee;
+import org.apache.struts2.showcase.model.Skill;
+
+/**
+ * EmployeeDao.
+ *
+ */
+
+public class EmployeeDao extends AbstractDao {
+
+ private static final long serialVersionUID = -6615310540042830594L;
+
+ protected SkillDao skillDao;
+
+ public void setSkillDao(SkillDao skillDao) {
+ this.skillDao = skillDao;
+ }
+
+ public Class getFeaturedClass() {
+ return Employee.class;
+ }
+
+ public Employee getEmployee( Long id ) {
+ return (Employee) get(id);
+ }
+
+ public Employee setSkills(Employee employee, List skillNames) {
+ if (employee!= null && skillNames != null) {
+ employee.setOtherSkills(new ArrayList());
+ for (int i = 0, j = skillNames.size(); i < j; i++) {
+ Skill skill = (Skill) skillDao.get((String) skillNames.get(i));
+ employee.getOtherSkills().add(skill);
+ }
+ }
+ return employee;
+ }
+
+ public Employee setSkills(Long empId, List skillNames) {
+ return setSkills((Employee) get(empId), skillNames);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java
new file mode 100644
index 000000000..f51421d5c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.dao;
+
+import org.apache.struts2.showcase.model.Skill;
+
+/**
+ * SkillDao.
+ *
+ */
+
+public class SkillDao extends AbstractDao {
+
+ private static final long serialVersionUID = -8160406514074630866L;
+
+ public Class getFeaturedClass() {
+ return Skill.class;
+ }
+
+ public Skill getSkill( String name ) {
+ return (Skill) get(name);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java
new file mode 100644
index 000000000..23cc287e5
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.exception;
+
+/**
+ * CreateException.
+ *
+ */
+
+public class CreateException extends StorageException {
+
+ private static final long serialVersionUID = 6734349565111633783L;
+
+ public CreateException(String message) {
+ super(message);
+ }
+
+ public CreateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CreateException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java
new file mode 100644
index 000000000..f2d2dfcbb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.exception;
+
+/**
+ * DeleteException.
+ *
+ */
+
+public class DeleteException extends StorageException {
+
+ private static final long serialVersionUID = -5286362812955627352L;
+
+ public DeleteException(String message) {
+ super(message);
+ }
+
+ public DeleteException(Throwable cause) {
+ super(cause);
+ }
+
+ public DeleteException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java
new file mode 100644
index 000000000..1ae17ddae
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.exception;
+
+/**
+ * DuplicateKeyException.
+ *
+ */
+
+public class DuplicateKeyException extends CreateException {
+
+ private static final long serialVersionUID = 989620752592415898L;
+
+ public DuplicateKeyException(String message) {
+ super(message);
+ }
+
+ public DuplicateKeyException(Throwable cause) {
+ super(cause);
+ }
+
+ public DuplicateKeyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java
new file mode 100644
index 000000000..7628bc2f5
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.exception;
+
+/**
+ * StorageException.
+ *
+ */
+
+public class StorageException extends Exception {
+
+ private static final long serialVersionUID = -2528721270540362905L;
+
+ public StorageException(String message) {
+ super(message);
+ }
+
+ public StorageException(Throwable cause) {
+ super(cause);
+ }
+
+ public StorageException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java
new file mode 100644
index 000000000..3f5023c81
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.exception;
+
+
+/**
+ * UpdateException.
+ *
+ */
+
+public class UpdateException extends StorageException {
+
+ private static final long serialVersionUID = -4728238600375630452L;
+
+
+ public UpdateException(String message) {
+ super(message);
+ }
+
+ public UpdateException(Throwable cause) {
+ super(cause);
+ }
+
+ public UpdateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java
new file mode 100644
index 000000000..5e3cc5679
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.filedownload;
+
+import java.io.InputStream;
+
+import org.apache.struts2.ServletActionContext;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * Demonstrates file resource download.
+ * Set filePath to the local file resource to download,
+ * relative to the application root ("/images/struts.gif").
+ *
+ */
+public class FileDownloadAction implements Action {
+
+ private String inputPath;
+ public void setInputPath(String value) {
+ inputPath = value;
+ }
+
+ public InputStream getInputStream() throws Exception {
+ return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
+ }
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java
new file mode 100644
index 000000000..e0b7c06a0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java
@@ -0,0 +1,85 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.fileupload;
+
+import java.io.File;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Show case File Upload example's action. FileUploadAction
+ *
+ */
+public class FileUploadAction extends ActionSupport {
+
+ private static final long serialVersionUID = 5156288255337069381L;
+
+ private String contentType;
+ private File upload;
+ private String fileName;
+ private String caption;
+
+ // since we are using the file name will be
+ // obtained through getter/setter of FileName
+ public String getUploadFileName() {
+ return fileName;
+ }
+ public void setUploadFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+
+ // since we are using the content type will be
+ // obtained through getter/setter of ContentType
+ public String getUploadContentType() {
+ return contentType;
+ }
+ public void setUploadContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+
+ // since we are using the File itself will be
+ // obtained through getter/setter of
+ public File getUpload() {
+ return upload;
+ }
+ public void setUpload(File upload) {
+ this.upload = upload;
+ }
+
+
+ public String getCaption() {
+ return caption;
+ }
+ public void setCaption(String caption) {
+ this.caption = caption;
+ }
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String upload() throws Exception {
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java
new file mode 100644
index 000000000..944db2df3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java
@@ -0,0 +1,66 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.fileupload;
+
+import java.io.File;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Showcase action - mutiple file upload using array.
+ *
+ * @version $Date$ $Id$
+ */
+public class MultipleFileUploadUsingArrayAction extends ActionSupport {
+
+ private File[] uploads;
+ private String[] uploadFileNames;
+ private String[] uploadContentTypes;
+
+ public File[] getUpload() { return this.uploads; }
+ public void setUpload(File[] upload) { this.uploads = upload; }
+
+ public String[] getUploadFileName() { return this.uploadFileNames; }
+ public void setUploadFileName(String[] uploadFileName) { this.uploadFileNames = uploadFileName; }
+
+ public String[] getUploadContentType() { return this.uploadContentTypes; }
+ public void setUploadContentType(String[] uploadContentType) { this.uploadContentTypes = uploadContentType; }
+
+
+ public String upload() throws Exception {
+ System.out.println("\n\n upload2");
+ System.out.println("files:");
+ for (File u: uploads) {
+ System.out.println("*** "+u+"\t"+u.length());
+ }
+ System.out.println("filenames:");
+ for (String n: uploadFileNames) {
+ System.out.println("*** "+n);
+ }
+ System.out.println("content types:");
+ for (String c: uploadContentTypes) {
+ System.out.println("*** "+c);
+ }
+ System.out.println("\n\n");
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java
new file mode 100644
index 000000000..2e6ea7d15
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java
@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.fileupload;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Showcase action - multiple file upload using List
+ * @version $Date$ $Id$
+ */
+public class MultipleFileUploadUsingListAction extends ActionSupport {
+
+ private List uploads = new ArrayList();
+ private List uploadFileNames = new ArrayList();
+ private List uploadContentTypes = new ArrayList();
+
+
+ public List getUpload() {
+ return this.uploads;
+ }
+ public void setUpload(List uploads) {
+ this.uploads = uploads;
+ }
+
+ public List getUploadFileName() {
+ return this.uploadFileNames;
+ }
+ public void setUploadFileName(List uploadFileNames) {
+ this.uploadFileNames = uploadFileNames;
+ }
+
+ public List getUploadContentType() {
+ return this.uploadContentTypes;
+ }
+ public void setUploadContentType(List contentTypes) {
+ this.uploadContentTypes = contentTypes;
+ }
+
+
+
+
+ public String upload() throws Exception {
+
+ System.out.println("\n\n upload1");
+ System.out.println("files:");
+ for (File u: uploads) {
+ System.out.println("*** "+u+"\t"+u.length());
+ }
+ System.out.println("filenames:");
+ for (String n: uploadFileNames) {
+ System.out.println("*** "+n);
+ }
+ System.out.println("content types:");
+ for (String c: uploadContentTypes) {
+ System.out.println("*** "+c);
+ }
+ System.out.println("\n\n");
+ return SUCCESS;
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java
new file mode 100644
index 000000000..a38a9cdd2
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.freemarker;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.views.freemarker.FreemarkerManager;
+import org.apache.struts2.views.freemarker.ScopesHashModel;
+
+import com.opensymphony.xwork2.util.OgnlValueStack;
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * This is an example of a custom FreemarkerManager, mean to be
+ * instantiated through Spring.
+ *
+ *
+ * It will add into Freemarker's model
+ * an utility class called {@link CustomFreemarkerManagerUtil} as a simple
+ * example demonstrating how to extends FreemarkerManager.
+ *
+ *
+ * The {@link CustomFreemarkerManagerUtil} will be created by Spring and
+ * injected through constructor injection.
+ *
+ */
+public class CustomFreemarkerManager extends FreemarkerManager {
+
+ private CustomFreemarkerManagerUtil util;
+
+ public CustomFreemarkerManager(CustomFreemarkerManagerUtil util) {
+ this.util = util;
+ }
+
+ protected void populateContext(ScopesHashModel model, ValueStack stack, Object action, HttpServletRequest request, HttpServletResponse response) {
+ super.populateContext(model, stack, action, request, response);
+ model.put("customFreemarkerManagerUtil", util);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java
new file mode 100644
index 000000000..d80932378
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.freemarker;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * This class is just a simple util that gets injected into
+ * {@link CustomFreemarkerManager} through Spring's constructor
+ * injection, serving as a simple example in Struts' Showcase.
+ */
+public class CustomFreemarkerManagerUtil {
+
+ public String getTodayDate() {
+ SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
+ return sdf.format(new Date());
+ }
+
+ public String getTimeNow() {
+ SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
+ return sdf.format(new Date());
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java
new file mode 100644
index 000000000..ce881b62c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.freemarker;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.Preparable;
+
+import java.text.DateFormatSymbols;
+
+/**
+ * Showcase action for freemarker templates.
+ */
+public class StandardTagsAction extends ActionSupport implements Preparable {
+
+ private String name;
+ private String[] gender;
+ private String[] months;
+
+ public void prepare() {
+ months = new DateFormatSymbols().getMonths();
+ name = StandardTagsAction.class.getName().substring(StandardTagsAction.class.getName().lastIndexOf(".")+1);
+ gender = new String[] { "Male", "Femal" };
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String[] getMonths() {
+ return months;
+ }
+
+ public void setMonths(String[] months) {
+ this.months = months;
+ }
+
+
+ public String[] getGender() {
+ return gender;
+ }
+
+ public void setGender(String[] gender) {
+ this.gender = gender;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java
new file mode 100644
index 000000000..e0c99b205
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class GetUpdatedHangmanAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 5506025785406043027L;
+
+ private Map session;
+ private Hangman hangman;
+
+
+ public String execute() throws Exception {
+ hangman = (Hangman) session.get(HangmanConstants.HANGMAN_SESSION_KEY);
+
+ System.out.println("\n\n\n");
+ System.out.println("hangman="+hangman);
+ System.out.println("available = "+hangman.getCharactersAvailable().size());
+ System.out.println("guess left="+hangman.guessLeft());
+ System.out.println("\n\n\n");
+
+ return SUCCESS;
+ }
+
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+ public Hangman getHangman() {
+ return hangman;
+ }
+ public void setHangman(Hangman hangman) {
+ this.hangman = hangman;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java
new file mode 100644
index 000000000..d15c223d4
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class GuessCharacterAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 9050915577007590674L;
+
+ private Map session;
+ private Character character;
+ private Hangman hangman;
+
+ public String execute() throws Exception {
+ hangman = (Hangman) session.get(HangmanConstants.HANGMAN_SESSION_KEY);
+ hangman.guess(character);
+
+ return SUCCESS;
+ }
+
+ public Hangman getHangman() {
+ return hangman;
+ }
+
+ public void setSession(Map session) {
+ this.session = session;
+ }
+
+ public void setCharacter(Character character) {
+ this.character = character;
+ }
+
+ public Character getCharacter() {
+ return this.character;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java
new file mode 100644
index 000000000..1fdf2daa4
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java
@@ -0,0 +1,109 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Hangman implements Serializable {
+
+ private static final long serialVersionUID = 8566954355839652509L;
+
+ private Vocab vocab;
+
+ private Boolean win = false;
+
+ private int guessLeft = 5;
+ public List charactersAvailable;
+ public List charactersGuessed;
+
+ public Hangman(Vocab vocab) {
+ // Arrays.asList(...) returns List that doesn't support remove(), hence
+ // we wrap it with an ArrayList to avoid UnsupportedOperationException
+ // when doing a remove()
+ charactersAvailable = new ArrayList(Arrays.asList(
+ new Character[] {
+ Character.valueOf('A'), Character.valueOf('B'), Character.valueOf('C'),
+ Character.valueOf('D'), Character.valueOf('E'), Character.valueOf('F'),
+ Character.valueOf('G'), Character.valueOf('H'), Character.valueOf('I'),
+ Character.valueOf('J'), Character.valueOf('K'), Character.valueOf('L'),
+ Character.valueOf('M'), Character.valueOf('N'), Character.valueOf('O'),
+ Character.valueOf('P'), Character.valueOf('Q'), Character.valueOf('R'),
+ Character.valueOf('S'), Character.valueOf('T'), Character.valueOf('U'),
+ Character.valueOf('V'), Character.valueOf('W'), Character.valueOf('X'),
+ Character.valueOf('Y'), Character.valueOf('Z')
+ }));
+ charactersGuessed = new ArrayList();
+ this.vocab = vocab;
+ }
+
+ public void guess(Character character) {
+ assert(character != null);
+
+ synchronized(charactersAvailable) {
+ if (guessLeft < 0) {
+ throw new HangmanException(
+ HangmanException.Type.valueOf("GAME_ENDED"), "Game already eneded");
+ }
+ Character characterInUpperCase = Character.toUpperCase(character);
+ boolean ok = charactersAvailable.remove(characterInUpperCase);
+ if (ok) {
+ charactersGuessed.add(characterInUpperCase);
+ if (! vocab.containCharacter(characterInUpperCase)) {
+ guessLeft = guessLeft - 1;
+ }
+ }
+ if (vocab.containsAllCharacter(charactersGuessed)) {
+ win = true;
+ }
+ System.out.println(" *********************************** "+win);
+ }
+ }
+
+ public Boolean isWin() {
+ return this.win;
+ }
+
+ public Vocab getVocab() {
+ return vocab;
+ }
+
+ public Boolean gameEnded() {
+ return ((guessLeft < 0) || win);
+ }
+
+ public Integer guessLeft() {
+ return guessLeft;
+ }
+
+ public List getCharactersAvailable() {
+ synchronized(charactersAvailable) {
+ return new ArrayList(charactersAvailable);
+ //return charactersAvailable;
+ }
+ }
+
+ public boolean characterGuessedBefore(Character character) {
+ return charactersGuessed.contains(character);
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java
new file mode 100644
index 000000000..bae60ded0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+public class HangmanConstants {
+ // keeps a Hangman object in HttpSession
+ public static final String HANGMAN_SESSION_KEY = "Hangman_Session_Key";
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java
new file mode 100644
index 000000000..feffb1c22
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+public class HangmanException extends RuntimeException {
+
+ private static final long serialVersionUID = -8500292863595941335L;
+
+ enum Type {
+ GAME_ENDED,
+ NO_VOCAB,
+ NO_VOCAB_SOURCE;
+ }
+
+
+ private Type type;
+
+ public HangmanException (Type type, String reason) {
+ super(reason);
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java
new file mode 100644
index 000000000..410acd85c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+public class HangmanService {
+
+ public VocabSource vocabSource;
+
+ public HangmanService(VocabSource vocabSource) {
+ this.vocabSource = vocabSource;
+ }
+
+ public Hangman startNewGame() {
+ return new Hangman(vocabSource.getRandomVocab());
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java
new file mode 100644
index 000000000..0ab443977
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java
@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class PropertiesVocabSource implements VocabSource {
+
+ private Properties prop;
+ private List vocabs;
+
+ public PropertiesVocabSource() {
+ }
+
+ public PropertiesVocabSource(Properties prop) {
+ assert(prop != null);
+ this.prop = prop;
+ vocabs = readVocab(prop);
+ }
+
+ public void setVocabProperties(Properties prop) {
+ assert(prop != null);
+ this.prop = prop;
+ vocabs = readVocab(prop);
+ }
+
+ public Vocab getRandomVocab() {
+ if (vocabs == null) {
+ throw new HangmanException(HangmanException.Type.valueOf("NO_VOCAB_SOURCE"), "No vocab source");
+ }
+ if (vocabs.size() <= 0) {
+ throw new HangmanException(HangmanException.Type.valueOf("NO_VOCAB"), "No vocab");
+ }
+ long vocabIndex = Math.round((Math.random() * (double)prop.size()));
+ vocabIndex = vocabIndex == vocabs.size() ? vocabs.size() - 1 : vocabIndex;
+ return vocabs.get((int)vocabIndex);
+ }
+
+ protected List readVocab(Properties prop) {
+ List vocabList = new ArrayList();
+
+ for (Map.Entry e : prop.entrySet()) {
+ String vocab = (String) e.getKey();
+ String hint = (String) e.getValue();
+
+ vocabList.add(new Vocab(vocab, hint));
+ }
+ return vocabList;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java
new file mode 100644
index 000000000..4c8aed099
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import static org.apache.struts2.showcase.hangman.HangmanConstants.HANGMAN_SESSION_KEY;
+
+import java.util.Map;
+
+import org.apache.struts2.interceptor.SessionAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class StartHangmanAction extends ActionSupport implements SessionAware {
+
+ private static final long serialVersionUID = 2333463075324892521L;
+
+ private HangmanService service;
+ private Hangman hangman;
+ private Map session;
+
+
+ public StartHangmanAction(HangmanService service) {
+ this.service = service;
+ }
+
+ public String execute() throws Exception {
+
+ hangman = service.startNewGame();
+ session.put(HANGMAN_SESSION_KEY, hangman);
+
+ return SUCCESS;
+ }
+
+ public Hangman getHangman() {
+ return hangman;
+ }
+
+
+ // === SessionAware ===
+ public void setSession(Map session) {
+ this.session = session;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java
new file mode 100644
index 000000000..da1cf1541
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java
@@ -0,0 +1,86 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Vocab implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private String vocab;
+ private String hint;
+ private Character[] characters; // character this vocab is made up of
+
+ public Vocab(String vocab, String hint) {
+ assert(vocab != null);
+ assert(hint != null);
+
+ this.vocab = vocab.toUpperCase();
+ this.hint = hint;
+ }
+
+ public String getVocab() { return this.vocab; }
+ public String getHint() { return this.hint; }
+
+ public Boolean containCharacter(Character character) {
+ assert(character != null);
+
+ return (vocab.contains(character.toString())) ? true : false;
+ }
+
+ public Character[] inCharacters() {
+ if (characters == null) {
+ char[] c = vocab.toCharArray();
+ characters = new Character[c.length];
+ for (int a=0; a< c.length; a++) {
+ characters[a] = Character.valueOf(c[a]);
+ }
+ }
+ return characters;
+ }
+
+ public boolean containsAllCharacter(List charactersGuessed) {
+ Character[] chars = inCharacters();
+ List tmpChars = Arrays.asList(chars);
+ return charactersGuessed.containsAll(tmpChars);
+ }
+
+ public static void main(String args[]) throws Exception {
+ Vocab v = new Vocab("JAVA", "a java word");
+
+ List list1= new ArrayList();
+ list1.add(new Character('J'));
+ list1.add(new Character('V'));
+
+ List list2 = new ArrayList();
+ list2.add(new Character('J'));
+ list2.add(new Character('V'));
+ list2.add(new Character('A'));
+
+ System.out.println(v.containsAllCharacter(list1));
+ System.out.println(v.containsAllCharacter(list2));
+
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java
new file mode 100644
index 000000000..b2d64a6a3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java
@@ -0,0 +1,25 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.hangman;
+
+public interface VocabSource {
+ Vocab getRandomVocab();
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java
new file mode 100644
index 000000000..d90b67547
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.integration;
+
+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 EditGangsterAction extends Action {
+
+ /* (non-Javadoc)
+ * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
+ // Some code to load the gangster from the db as necessary
+
+ return mapping.findForward("success");
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java
new file mode 100644
index 000000000..5bb5c4142
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java
@@ -0,0 +1,108 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.integration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts.action.ActionErrors;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.action.ActionMessage;
+import org.apache.struts.validator.ValidatorForm;
+
+public class GangsterForm extends ValidatorForm {
+
+ private String name;
+ private String age;
+ private String description;
+ private boolean bustedBefore;
+
+ /* (non-Javadoc)
+ * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest)
+ */
+ @Override
+ public void reset(ActionMapping arg0, HttpServletRequest arg1) {
+ bustedBefore = false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.struts.action.ActionForm#validate(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest)
+ */
+ @Override
+ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
+ ActionErrors errors = super.validate(mapping, request);
+ if (name == null || name.length() == 0) {
+ errors.add("name", new ActionMessage("The name must not be blank"));
+ }
+
+ return errors;
+ }
+
+ /**
+ * @return the age
+ */
+ public String getAge() {
+ return age;
+ }
+ /**
+ * @param age the age to set
+ */
+ public void setAge(String age) {
+ this.age = age;
+ }
+ /**
+ * @return the bustedBefore
+ */
+ public boolean isBustedBefore() {
+ return bustedBefore;
+ }
+ /**
+ * @param bustedBefore the bustedBefore to set
+ */
+ public void setBustedBefore(boolean bustedBefore) {
+ this.bustedBefore = bustedBefore;
+ }
+ /**
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+ /**
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java
new file mode 100644
index 000000000..ab68d7e58
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java
@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.integration;
+
+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.action.ActionMessage;
+import org.apache.struts.action.ActionMessages;
+
+public class SaveGangsterAction extends Action {
+
+ /* (non-Javadoc)
+ * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+ // Some code to save the gangster to the db as necessary
+ GangsterForm gform = (GangsterForm) form;
+ ActionMessages messages = new ActionMessages();
+ messages.add("msg", new ActionMessage("Gangster "+gform.getName()+" added successfully"));
+ addMessages(request, messages);
+
+ return mapping.findForward("success");
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java
new file mode 100644
index 000000000..d1bcc234e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java
@@ -0,0 +1,122 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.jsf;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.struts2.showcase.action.EmployeeAction;
+import org.apache.struts2.showcase.dao.SkillDao;
+import org.apache.struts2.showcase.model.Employee;
+import org.apache.struts2.showcase.model.Skill;
+
+/**
+ * Overriding the EmployeeAction to main provide getters returning the data in
+ * the form required by the JSF components
+ */
+public class JsfEmployeeAction extends EmployeeAction {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creating a default employee and main skill, since the JSF EL can't handle
+ * creating new objects as necessary
+ *
+ */
+ public JsfEmployeeAction() {
+ Employee e = new Employee();
+ e.setMainSkill(new Skill());
+ setCurrentEmployee(e);
+ }
+
+ private SkillDao skillDao;
+
+ public void setSkillDao(SkillDao skillDao) {
+ this.skillDao = skillDao;
+ }
+
+ /**
+ * Returning a List because the JSF dataGrid can't handle a Set for some
+ * reason
+ */
+ @Override
+ public Collection getAvailableItems() {
+ return new ArrayList(super.getAvailableItems());
+ }
+
+ /**
+ * Changing the String array into a Map
+ */
+ public Map getAvailablePositionsAsMap() {
+ Map map = new LinkedHashMap();
+ for (String val : super.getAvailablePositions()) {
+ map.put(val, val);
+ }
+ return map;
+ }
+
+ /**
+ * Converting the list into a map
+ */
+ public Map getAvailableLevelsAsMap() {
+ Map map = new LinkedHashMap();
+ for (Object val : super.getAvailableLevels()) {
+ map.put(val, val);
+ }
+ return map;
+ }
+
+ /**
+ * Converting the Skill object list into a map
+ */
+ public Map getAvailableSkills() {
+ Map map = new HashMap();
+ for (Object val : skillDao.findAll()) {
+ Skill skill = (Skill) val;
+ map.put(skill.getDescription(), skill.getName());
+ }
+ return map;
+ }
+
+ /**
+ * Gets the selected Skill objects as a list
+ */
+ public List getSelectedSkillsAsList() {
+ System.out.println("asked for skills");
+ List list = new ArrayList();
+ List skills = super.getSelectedSkills();
+ if (skills != null) {
+ for (Object val : skills) {
+ if (val instanceof Skill) {
+ list.add(((Skill) val).getDescription());
+ } else {
+ Skill skill = skillDao.getSkill((String) val);
+ list.add(skill.getDescription());
+ }
+ }
+ }
+ return list;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java
new file mode 100644
index 000000000..ed93b20df
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java
@@ -0,0 +1,176 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.model;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Employee.
+ *
+ */
+
+public class Employee implements IdEntity {
+
+ private static final long serialVersionUID = -6226845151026823748L;
+
+ private Long empId; //textfield w/ conversion
+ private String firstName;
+ private String lastName;
+ private Date birthDate; //datepicker
+ private Float salary; //textfield w/ conversion
+ private boolean married; //checkbox
+ private String position; //combobox
+ private Skill mainSkill; //select
+ private List otherSkills; //doubleSelect
+ private String password; //password
+ private String level; //radio
+ private String comment; //textarea
+
+ public Employee() {
+ }
+
+ public Employee(Long empId, String firstName, String lastName) {
+ this.empId = empId;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public Employee(Long empId, String firstName, String lastName, Date birthDate, Float salary, boolean married, String position, Skill mainSkill, List otherSkills, String password, String level, String comment) {
+ this.empId = empId;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.birthDate = birthDate;
+ this.salary = salary;
+ this.married = married;
+ this.position = position;
+ this.mainSkill = mainSkill;
+ this.otherSkills = otherSkills;
+ this.password = password;
+ this.level = level;
+ this.comment = comment;
+ }
+
+ public Long getEmpId() {
+ return empId;
+ }
+
+ public void setEmpId(Long empId) {
+ this.empId = empId;
+ }
+
+ public Serializable getId() {
+ return getEmpId();
+ }
+
+ public void setId(Serializable id) {
+ setEmpId((Long) id);
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public Date getBirthDate() {
+ return birthDate;
+ }
+
+ public void setBirthDate(Date birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ public Float getSalary() {
+ return salary;
+ }
+
+ public void setSalary(Float salary) {
+ this.salary = salary;
+ }
+
+ public boolean isMarried() {
+ return married;
+ }
+
+ public void setMarried(boolean married) {
+ this.married = married;
+ }
+
+ public String getPosition() {
+ return position;
+ }
+
+ public void setPosition(String position) {
+ this.position = position;
+ }
+
+ public Skill getMainSkill() {
+ return mainSkill;
+ }
+
+ public void setMainSkill(Skill mainSkill) {
+ this.mainSkill = mainSkill;
+ }
+
+ public List getOtherSkills() {
+ return otherSkills;
+ }
+
+ public void setOtherSkills(List otherSkills) {
+ this.otherSkills = otherSkills;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getLevel() {
+ return level;
+ }
+
+ public void setLevel(String level) {
+ this.level = level;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java
new file mode 100644
index 000000000..9e1353803
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.model;
+
+import java.io.Serializable;
+
+/**
+ * IdEntity. Interface.
+ *
+ */
+
+public interface IdEntity extends Serializable {
+
+ Serializable getId ();
+
+ void setId ( Serializable id );
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java
new file mode 100644
index 000000000..e105ba0db
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.model;
+
+import java.io.Serializable;
+
+/**
+ * Skill.
+ *
+ */
+
+public class Skill implements IdEntity {
+
+ private static final long serialVersionUID = -4150317722693212439L;
+
+ private String name;
+ private String description;
+
+ public Skill() {
+ }
+
+ public Skill(String name, String description) {
+ this.name = name;
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Serializable getId() {
+ return getName();
+ }
+
+ public void setId(Serializable id) {
+ setName((String) id);
+ }
+
+ public String toString() {
+ return getName();
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java
new file mode 100644
index 000000000..aa9591fb6
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java
@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.modelDriven;
+
+import java.io.Serializable;
+
+/**
+ * A model class to be used by the simple Model-Driven example.
+ *
+ */
+public class Gangster implements Serializable {
+
+ private static final long serialVersionUID = 3688389475320294992L;
+
+ private String name;
+ private int age;
+ private String description;
+ private boolean bustedBefore;
+
+ public int getAge() {
+ return age;
+ }
+ public void setAge(int age) {
+ this.age = age;
+ }
+ public boolean isBustedBefore() {
+ return bustedBefore;
+ }
+ public void setBustedBefore(boolean bustedBefore) {
+ this.bustedBefore = bustedBefore;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java
new file mode 100644
index 000000000..4ab545710
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.modelDriven;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.ModelDriven;
+
+/**
+ * Action to demonstrate simple model-driven feature of the framework.
+ *
+ */
+public class ModelDrivenAction extends ActionSupport implements ModelDriven {
+
+ private static final long serialVersionUID = 1271130427666936592L;
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ public Object getModel() {
+ return new Gangster();
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java
new file mode 100644
index 000000000..208f23a0a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java
@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.person;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.struts2.config.Result;
+import org.apache.struts2.config.Results;
+import org.apache.struts2.dispatcher.ServletRedirectResult;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * EditPerson
+ *
+ */
+@Result(name="list", value="listPeople.action", type=ServletRedirectResult.class)
+public class EditPersonAction extends ActionSupport {
+
+ private static final long serialVersionUID = 7699491775215130850L;
+
+ PersonManager personManager;
+ List persons = new ArrayList();
+
+ public void setPersonManager(PersonManager personManager) {
+ this.personManager = personManager;
+ }
+
+ public List getPersons() {
+ return persons;
+ }
+
+ public void setPersons(List persons) {
+ this.persons = persons;
+ }
+
+ /**
+ * A default implementation that does nothing an returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String execute() throws Exception {
+ persons.addAll(personManager.getPeople());
+ return SUCCESS;
+ }
+
+ /**
+ * A default implementation that does nothing an returns "success".
+ *
+ * @return {@link #SUCCESS}
+ */
+ public String save() throws Exception {
+
+ // Set people = personManager.getPeople();
+
+ for ( Iterator iter = persons.iterator(); iter.hasNext();) {
+ Person p = (Person) iter.next();
+ personManager.getPeople().remove(p);
+ personManager.getPeople().add(p);
+ }
+ return "list";
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java
new file mode 100644
index 000000000..4c3bd25c0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java
@@ -0,0 +1,56 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.person;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts2.config.Result;
+import org.apache.struts2.views.freemarker.FreemarkerResult;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class ListPeopleAction extends ActionSupport {
+
+ private static final long serialVersionUID = 3608017189783645371L;
+
+ PersonManager personManager;
+ List people = new ArrayList();
+
+ public void setPersonManager(PersonManager personManager) {
+ this.personManager = personManager;
+ }
+
+ public String execute() {
+ people.addAll(personManager.getPeople());
+
+ return SUCCESS;
+ }
+
+ public List getPeople() {
+ return people;
+ }
+
+ public int getPeopleCount() {
+ return people.size();
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java
new file mode 100644
index 000000000..b477c5a5e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.person;
+
+import org.apache.struts2.config.ParentPackage;
+import org.apache.struts2.config.Result;
+import org.apache.struts2.config.Results;
+import org.apache.struts2.views.freemarker.FreemarkerResult;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+@ParentPackage("person")
+public class NewPersonAction extends ActionSupport {
+
+ private static final long serialVersionUID = 200410824352645515L;
+
+ PersonManager personManager;
+ Person person;
+
+ public void setPersonManager(PersonManager personManager) {
+ this.personManager = personManager;
+ }
+
+ public String execute() {
+ personManager.createPerson(person);
+
+ return SUCCESS;
+ }
+
+ public Person getPerson() {
+ return person;
+ }
+
+ public void setPerson(Person person) {
+ this.person = person;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java
new file mode 100644
index 000000000..440966a45
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java
@@ -0,0 +1,86 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.person;
+
+/**
+ */
+public class Person {
+ Long id;
+ String name;
+ String lastName;
+
+ public Person() {
+ }
+
+ public Person(Long id, String name, String lastName) {
+ this.id = id;
+ this.name = name;
+ this.lastName = lastName;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final Person person = (Person) o;
+
+ if (id != null ? !id.equals(person.id) : person.id != null) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return (id != null ? id.hashCode() : 0);
+ }
+
+
+ public String toString() {
+ return "Person{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ ", lastName='" + lastName + '\'' +
+ '}';
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java
new file mode 100644
index 000000000..cf7e28c28
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.person;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ */
+public class PersonManager {
+ private static Set people = new HashSet(5);
+ private static long COUNT = 5;
+
+ static {
+ // create some imaginary persons
+ Person p1 = new Person(new Long(1), "Patrick", "Lightbuddie");
+ Person p2 = new Person(new Long(2), "Jason", "Carrora");
+ Person p3 = new Person(new Long(3), "Alexandru", "Papesco");
+ Person p4 = new Person(new Long(4), "Jay", "Boss");
+ Person p5 = new Person(new Long(5), "Rainer", "Hermanos");
+ people.add(p1);
+ people.add(p2);
+ people.add(p3);
+ people.add(p4);
+ people.add(p5);
+ }
+
+ public void createPerson(Person person) {
+ person.setId(new Long(++COUNT));
+ people.add(person);
+ }
+
+ public void updatePerson(Person person) {
+ people.add(person);
+ }
+
+ public Set getPeople() {
+ return people;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
new file mode 100644
index 000000000..80d5c98e3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java
@@ -0,0 +1,224 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.source;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+
+import org.apache.struts2.util.ServletContextAware;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+
+/**
+ * Processes configuration, page, and action class paths to create snippets
+ * of the files for display.
+ */
+public class ViewSourceAction extends ActionSupport implements ServletContextAware {
+
+ private String page;
+ private String className;
+ private String config;
+
+ private List pageLines;
+ private List classLines;
+ private List configLines;
+
+ private int configLine;
+ private int padding = 10;
+
+ private ServletContext servletContext;
+
+ public String execute() throws MalformedURLException, IOException {
+
+ if (page != null && page.trim().length() > 0) {
+
+ InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//")+1), getClass());
+ page = page.replace("//", "/");
+
+ if (in == null) {
+ in = servletContext.getResourceAsStream(page);
+ while (in == null && page.indexOf('/', 1) > 0) {
+ page = page.substring(page.indexOf('/', 1));
+ in = servletContext.getResourceAsStream(page);
+ }
+ }
+ pageLines = read(in, -1);
+
+ if (in != null) {
+ in.close();
+ }
+ }
+
+ if (className != null && className.trim().length() > 0) {
+ className = "/" + className.replace('.', '/') + ".java";
+ InputStream in = getClass().getResourceAsStream(className);
+ if (in == null) {
+ in = servletContext.getResourceAsStream("/WEB-INF/src"+className);
+ }
+ classLines = read(in, -1);
+
+ if (in != null) {
+ in.close();
+ }
+ }
+
+ if (config != null && config.trim().length() > 0) {
+ int pos = config.lastIndexOf(':');
+ configLine = Integer.parseInt(config.substring(pos+1));
+ config = config.substring(0, pos).replace("//", "/");
+ configLines = read(new URL(config).openStream(), configLine);
+ }
+ return SUCCESS;
+ }
+
+ /**
+ * @param className the className to set
+ */
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ /**
+ * @param config the config to set
+ */
+ public void setConfig(String config) {
+ this.config = config;
+ }
+
+ /**
+ * @param page the page to set
+ */
+ public void setPage(String page) {
+ this.page = page;
+ }
+
+ /**
+ * @param padding the padding to set
+ */
+ public void setPadding(int padding) {
+ this.padding = padding;
+ }
+
+ /**
+ * @return the classLines
+ */
+ public List getClassLines() {
+ return classLines;
+ }
+
+ /**
+ * @return the configLines
+ */
+ public List getConfigLines() {
+ return configLines;
+ }
+
+ /**
+ * @return the pageLines
+ */
+ public List getPageLines() {
+ return pageLines;
+ }
+
+ /**
+ * @return the className
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * @return the config
+ */
+ public String getConfig() {
+ return config;
+ }
+
+ /**
+ * @return the page
+ */
+ public String getPage() {
+ return page;
+ }
+
+ /**
+ * @return the configLine
+ */
+ public int getConfigLine() {
+ return configLine;
+ }
+
+ /**
+ * @return the padding
+ */
+ public int getPadding() {
+ return padding;
+ }
+
+ /**
+ * Reads in a strea, optionally only including the target line number
+ * and its padding
+ *
+ * @param in The input stream
+ * @param targetLineNumber The target line number, negative to read all
+ * @return A list of lines
+ */
+ private List read(InputStream in, int targetLineNumber) {
+ List snippet = null;
+ if (in != null) {
+ snippet = new ArrayList();
+ int startLine = 0;
+ int endLine = Integer.MAX_VALUE;
+ if (targetLineNumber > 0) {
+ startLine = targetLineNumber - padding;
+ endLine = targetLineNumber + padding;
+ }
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+
+ int lineno = 0;
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lineno++;
+ if (lineno >= startLine && lineno <= endLine) {
+ snippet.add(line);
+ }
+ }
+ } catch (Exception ex) {
+ // ignoring as snippet not available isn't a big deal
+ }
+ }
+ return snippet;
+ }
+
+ public void setServletContext(ServletContext arg0) {
+ this.servletContext = arg0;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java
new file mode 100644
index 000000000..a8b350c85
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.actionPrefix;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class SubmitAction extends ActionSupport {
+
+ private static final long serialVersionUID = -7832803019378213087L;
+
+ private String text;
+
+ public String getText() { return text; }
+ public void setText(String text) { this.text = text; }
+
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ public String alternateMethod() {
+ return "methodPrefixResult";
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java
new file mode 100644
index 000000000..6de46d258
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.actiontag;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class ActionTagDemo extends ActionSupport {
+
+ private static final long serialVersionUID = -2749145880590245184L;
+
+ public String show() throws Exception {
+ return SUCCESS;
+ }
+
+ public String doInclude() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java
new file mode 100644
index 000000000..a47ee62a0
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.iteratortag;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.Validateable;
+
+/**
+ *
+ */
+public class AppendIteratorTagDemo extends ActionSupport implements Validateable {
+
+ private static final long serialVersionUID = -6525059998526094664L;
+
+ private String iteratorValue1;
+ private String iteratorValue2;
+
+
+ public void validate() {
+ if (iteratorValue1 == null || iteratorValue1.trim().length() <= 0 ) {
+ addFieldError("iteratorValue1", "iterator value 1 cannot be empty");
+ }
+ else if (iteratorValue1.trim().indexOf(",") <= 0) {
+ addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated");
+ }
+ if (iteratorValue2 == null || iteratorValue2.trim().length() <= 0) {
+ addFieldError("iteratorValue2", "iterator value 2 cannot be empty");
+ }
+ else if (iteratorValue2.trim().indexOf(",") <= 0) {
+ addFieldError("iteratorValue2", "iterator value 2 needs to be comma separated");
+ }
+ }
+
+
+
+
+ public String getIteratorValue1() {
+ return iteratorValue1;
+ }
+ public void setIteratorValue1(String iteratorValue1) {
+ this.iteratorValue1 = iteratorValue1;
+ }
+
+
+
+ public String getIteratorValue2() {
+ return iteratorValue2;
+ }
+ public void setIteratorValue2(String iteratorValue2) {
+ this.iteratorValue2 = iteratorValue2;
+ }
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java
new file mode 100644
index 000000000..f4b74fd2a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java
@@ -0,0 +1,69 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.iteratortag;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public class IteratorGeneratorTagDemo extends ActionSupport {
+
+ private static final long serialVersionUID = 6893616642389337039L;
+
+ private String value;
+ private Integer count;
+ private String separator;
+
+
+ public String getValue() {
+ return value;
+ }
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+
+ public Integer getCount() {
+ return count;
+ }
+ public void setCount(Integer count) {
+ this.count = count;
+ }
+
+
+
+ public String getSeparator() {
+ return this.separator;
+ }
+ public void setSeparator(String separator) {
+ this.separator = separator;
+ }
+
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java
new file mode 100644
index 000000000..64dbe87b1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java
@@ -0,0 +1,81 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.iteratortag;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.Validateable;
+
+
+/**
+ */
+public class MergeIteratorTagDemo extends ActionSupport implements Validateable {
+
+ private static final long serialVersionUID = 4401107963952961695L;
+
+ private String iteratorValue1;
+ private String iteratorValue2;
+
+
+ public void validate() {
+ if (iteratorValue1 == null || iteratorValue1.trim().length() <= 0 ) {
+ addFieldError("iteratorValue1", "iterator value 1 cannot be empty");
+ }
+ else if (iteratorValue1.trim().indexOf(",") <= 0) {
+ addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated");
+ }
+ if (iteratorValue2 == null || iteratorValue2.trim().length() <= 0) {
+ addFieldError("iteratorValue2", "iterator value 2 cannot be empty");
+ }
+ else if (iteratorValue2.trim().indexOf(",") <= 0) {
+ addFieldError("iteratorValue2", "iterator value 2 needs to be comma separated");
+ }
+ }
+
+
+
+ public String getIteratorValue1() {
+ return this.iteratorValue1;
+ }
+ public void setIteratorValue1(String iteratorValue1) {
+ this.iteratorValue1 = iteratorValue1;
+ }
+
+
+
+ public String getIteratorValue2() {
+ return this.iteratorValue2;
+ }
+ public void setIteratorValue2(String iteratorValue2) {
+ this.iteratorValue2 = iteratorValue2;
+ }
+
+
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java
new file mode 100644
index 000000000..c4002e908
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.tag.nonui.iteratortag;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.Validateable;
+
+/**
+ *
+ */
+public class SubsetIteratorTagDemo extends ActionSupport implements Validateable {
+
+ private static final long serialVersionUID = -8151855954644052650L;
+
+ private String iteratorValue;
+ private Integer count;
+ private Integer start;
+
+
+ public void validate() {
+ if (iteratorValue == null || iteratorValue.trim().length() <= 0 ) {
+ addFieldError("iteratorValue1", "iterator value 1 cannot be empty");
+ }
+ else if (iteratorValue.trim().indexOf(",") <= 0) {
+ addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated");
+ }
+ }
+
+
+
+ public String getIteratorValue() {
+ return this.iteratorValue;
+ }
+ public void setIteratorValue(String iteratorValue) {
+ this.iteratorValue = iteratorValue;
+ }
+
+
+
+ public Integer getCount() {
+ return this.count;
+ }
+ public void setCount(Integer count) {
+ this.count = count;
+ }
+
+
+
+ public Integer getStart() {
+ return this.start;
+ }
+ public void setStart(Integer start) {
+ this.start = start;
+ }
+
+
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java
new file mode 100644
index 000000000..6ec8046eb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java
@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.token;
+
+import java.util.Date;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example to illustrate the token and token-session interceptor.
+ *
+ */
+public class TokenAction extends ActionSupport {
+
+ private static final long serialVersionUID = 616150375751184884L;
+
+ private int amount;
+
+ public String execute() throws Exception {
+ // transfer from source to destination
+
+ Integer balSource = (Integer) ActionContext.getContext().getSession().get("balanceSource");
+ Integer balDest = (Integer) ActionContext.getContext().getSession().get("balanceDestination");
+
+ Integer newSource = new Integer(balSource.intValue() - amount);
+ Integer newDest = new Integer(balDest.intValue() + amount);
+
+ ActionContext.getContext().getSession().put("balanceSource", newSource);
+ ActionContext.getContext().getSession().put("balanceDestination", newDest);
+ ActionContext.getContext().getSession().put("time", new Date());
+
+ Thread.sleep(2000); // to simulate processing time
+
+ return SUCCESS;
+ }
+
+ public String input() throws Exception {
+ // prepare input form
+ Integer balSource = (Integer) ActionContext.getContext().getSession().get("balanceSource");
+ Integer balDest = (Integer) ActionContext.getContext().getSession().get("balanceDestination");
+
+ if (balSource == null) {
+ // first time set up an initial account balance
+ balSource = new Integer(1200);
+ ActionContext.getContext().getSession().put("balanceSource", balSource);
+ }
+
+ if (balDest == null) {
+ // first time set up an initial account balance
+ balDest = new Integer(2500);
+ ActionContext.getContext().getSession().put("balanceDestination", balDest);
+ }
+
+ return INPUT;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java
new file mode 100644
index 000000000..346745d3d
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+public abstract class AbstractValidationActionSupport extends ActionSupport {
+
+ public String submit() throws Exception {
+ return "success";
+ }
+
+ public String input() throws Exception {
+ return "input";
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java
new file mode 100644
index 000000000..e1c4c41bf
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+import java.sql.Date;
+
+/**
+ */
+
+// START SNIPPET: fieldValidatorsExample
+
+public class FieldValidatorsExampleAction extends AbstractValidationActionSupport {
+
+ private static final long serialVersionUID = -4829381083003175423L;
+
+ private String requiredValidatorField = null;
+ private String requiredStringValidatorField = null;
+ private Integer integerValidatorField = null;
+ private Date dateValidatorField = null;
+ private String emailValidatorField = null;
+ private String urlValidatorField = null;
+ private String stringLengthValidatorField = null;
+ private String regexValidatorField = null;
+ private String fieldExpressionValidatorField = null;
+
+
+
+ public Date getDateValidatorField() {
+ return dateValidatorField;
+ }
+ public void setDateValidatorField(Date dateValidatorField) {
+ this.dateValidatorField = dateValidatorField;
+ }
+ public String getEmailValidatorField() {
+ return emailValidatorField;
+ }
+ public void setEmailValidatorField(String emailValidatorField) {
+ this.emailValidatorField = emailValidatorField;
+ }
+ public Integer getIntegerValidatorField() {
+ return integerValidatorField;
+ }
+ public void setIntegerValidatorField(Integer integerValidatorField) {
+ this.integerValidatorField = integerValidatorField;
+ }
+ public String getRegexValidatorField() {
+ return regexValidatorField;
+ }
+ public void setRegexValidatorField(String regexValidatorField) {
+ this.regexValidatorField = regexValidatorField;
+ }
+ public String getRequiredStringValidatorField() {
+ return requiredStringValidatorField;
+ }
+ public void setRequiredStringValidatorField(String requiredStringValidatorField) {
+ this.requiredStringValidatorField = requiredStringValidatorField;
+ }
+ public String getRequiredValidatorField() {
+ return requiredValidatorField;
+ }
+ public void setRequiredValidatorField(String requiredValidatorField) {
+ this.requiredValidatorField = requiredValidatorField;
+ }
+ public String getStringLengthValidatorField() {
+ return stringLengthValidatorField;
+ }
+ public void setStringLengthValidatorField(String stringLengthValidatorField) {
+ this.stringLengthValidatorField = stringLengthValidatorField;
+ }
+ public String getFieldExpressionValidatorField() {
+ return fieldExpressionValidatorField;
+ }
+ public void setFieldExpressionValidatorField(
+ String fieldExpressionValidatorField) {
+ this.fieldExpressionValidatorField = fieldExpressionValidatorField;
+ }
+
+ public String getUrlValidatorField() {
+ return urlValidatorField;
+ }
+
+ public void setUrlValidatorField(String urlValidatorField) {
+ this.urlValidatorField = urlValidatorField;
+ }
+}
+
+
+// END SNIPPET: fieldValidatorsExample
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java
new file mode 100644
index 000000000..447b17c79
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+/**
+ */
+
+// START SNIPPET: nonFieldValidatorsExample
+
+public class NonFieldValidatorsExampleAction extends AbstractValidationActionSupport {
+
+ private static final long serialVersionUID = -524460368233581186L;
+
+ private String someText;
+ private String someTextRetype;
+ private String someTextRetypeAgain;
+
+ public String getSomeText() {
+ return someText;
+ }
+ public void setSomeText(String someText) {
+ this.someText = someText;
+ }
+ public String getSomeTextRetype() {
+ return someTextRetype;
+ }
+ public void setSomeTextRetype(String someTextRetype) {
+ this.someTextRetype = someTextRetype;
+ }
+ public String getSomeTextRetypeAgain() {
+ return someTextRetypeAgain;
+ }
+ public void setSomeTextRetypeAgain(String someTextRetypeAgain) {
+ this.someTextRetypeAgain = someTextRetypeAgain;
+ }
+}
+
+
+// END SNIPPET: nonFieldValidatorsExample
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java
new file mode 100644
index 000000000..81e27360b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+
+// START SNIPPET: quizAction
+
+public class QuizAction extends ActionSupport {
+
+ private static final long serialVersionUID = -7505437345373234225L;
+
+ String name;
+ int age;
+ String answer;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getAnswer() {
+ return answer;
+ }
+
+ public void setAnswer(String answer) {
+ this.answer = answer;
+ }
+}
+
+// END SNIPPET: quizAction
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java
new file mode 100644
index 000000000..99bf87479
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public class SubmitApplication extends ActionSupport {
+
+ private String name;
+ private Integer age;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ return this.name;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ public Integer getAge() {
+ return age;
+ }
+
+ public String submitApplication() throws Exception {
+ return SUCCESS;
+ }
+
+ public String applicationOk() throws Exception {
+ addActionMessage("Your application looks ok.");
+ return SUCCESS;
+ }
+ public String cancelApplication() throws Exception {
+ addActionMessage("So you have decided to cancel the application");
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java
new file mode 100644
index 000000000..111f8be52
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+import java.sql.Date;
+
+/**
+ */
+public class User {
+
+ private String name;
+ private Integer age;
+ private Date birthday;
+
+
+ public Integer getAge() {
+ return age;
+ }
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ public Date getBirthday() {
+ return birthday;
+ }
+ public void setBirthday(Date birthday) {
+ this.birthday = birthday;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java
new file mode 100644
index 000000000..91391a314
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.validation;
+
+
+// START SNIPPET: visitorValidatorsExample
+
+public class VisitorValidatorsExampleAction extends AbstractValidationActionSupport {
+
+ private static final long serialVersionUID = 4375454086939598216L;
+
+ private User user;
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+}
+
+
+// END SNIPPET: visitorValidatorsExample
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java
new file mode 100644
index 000000000..e449d9f09
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.wait;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * Example to illustrate the execAndWait interceptor.
+ *
+ */
+public class LongProcessAction extends ActionSupport {
+
+ private static final long serialVersionUID = 2471910747833998708L;
+
+ private int time;
+
+ public int getTime() {
+ return time;
+ }
+
+ public void setTime(int time) {
+ this.time = time;
+ }
+
+ public String execute() throws Exception {
+ System.err.println("time: " + time);
+ Thread.sleep(time);
+
+ return SUCCESS;
+ }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java
new file mode 100644
index 000000000..d888e2929
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java
@@ -0,0 +1,103 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.showcase.xslt;
+
+import java.util.Map;
+import java.util.Properties;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+import org.apache.struts2.interceptor.ServletRequestAware;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class JVMAction implements ServletRequestAware {
+
+ private ImportantInfo info;
+ private Map environment;
+
+ /** Captured only to show that undesired data can creep into the result. */
+ private HttpServletRequest servletRequest;
+
+
+ public String execute() {
+ environment = System.getenv();
+ Properties props = System.getProperties();
+
+ String classpath = environment.get("CLASSPATH");
+ info = new ImportantInfo(classpath, props);
+
+ return ActionSupport.SUCCESS;
+ }
+
+
+ public HttpServletRequest getServletRequest() {
+ return servletRequest;
+ }
+
+ public void setServletRequest(HttpServletRequest servletRequest) {
+ this.servletRequest = servletRequest;
+ }
+
+ public Map getEnvironment() {
+ return environment;
+ }
+
+ public void setEnvironment(Map environment) {
+ this.environment = environment;
+ }
+
+
+ public ImportantInfo getInfo() {
+ return info;
+ }
+
+ public void setInfo(ImportantInfo info) {
+ this.info = info;
+ }
+
+ public class ImportantInfo {
+ private String classpath;
+ private Properties systemProperties;
+
+
+ public ImportantInfo(String classpath, Properties properties) {
+ this.classpath = classpath;
+ this.systemProperties = properties;
+ }
+
+ public String getClasspath() {
+ return classpath;
+ }
+
+ public void setClasspath(String classpath) {
+ this.classpath = classpath;
+ }
+
+ public Properties getSystemProperties() {
+ return systemProperties;
+ }
+
+ public void setSystemProperties(Properties systemProperties) {
+ this.systemProperties = systemProperties;
+ }
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt
new file mode 100644
index 000000000..dd5b3a58a
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/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_2_0_X/apps/showcase/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt
new file mode 100644
index 000000000..28aacd493
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt
@@ -0,0 +1,6 @@
+Apache Struts
+Copyright 2000-2007 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+Nifty Corners (http://www.html.it/articoli/nifty/index.html).
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties
new file mode 100644
index 000000000..24a39d45c
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties
@@ -0,0 +1,7 @@
+save=Save
+
+item.edit=Edit {0}
+item.create=Create {0}
+item.list={0} List
+
+token.transfer.time=The bank transfer was executed at {0,date,HH:mm:ss MM-dd-yyyy}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties
new file mode 100644
index 000000000..0dc66efa8
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties
@@ -0,0 +1,7 @@
+save=Speichern
+
+item.edit={0} bearbeiten
+item.create={0} neu anlegen
+item.list={0}-Liste
+
+token.transfer.time=Die \u00dcberweisung wurde am {0,date,HH:mm:ss MM-dd-yyyy} durchgef\u00fchrt
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties
new file mode 100644
index 000000000..226f3de08
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties
@@ -0,0 +1,31 @@
+#
+# Log4J Settings for log4j 1.2.x (via jakarta-commons-logging)
+#
+# The five logging levels used by Log are (in order):
+#
+# 1. DEBUG (the least serious)
+# 2. INFO
+# 3. WARN
+# 4. ERROR
+# 5. FATAL (the most serious)
+
+
+# Set root logger level to WARN and append to stdout
+log4j.rootLogger=WARN, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+# Pattern to output the caller's file name and line number.
+log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n
+
+# Print only messages of level ERROR or above in the package noModule.
+log4j.logger.noModule=FATAL
+
+# OpenSymphony Stuff
+log4j.logger.com.opensymphony=INFO
+log4j.logger.org.apache.struts2=DEBUG
+
+# Spring Stuff
+log4j.logger.org.springframework=INFO
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl b/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl
new file mode 100644
index 000000000..544f44e60
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl
@@ -0,0 +1,6 @@
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt
new file mode 100644
index 000000000..bf501834e
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt
@@ -0,0 +1,35 @@
+/*
+ * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+
+/**
+ * @version $Date$ $Id$
+ */
+public class Address {
+
+ private String id;
+ private String address;
+
+ public String getId() { return id; }
+ public void setId(String id) { this.id = id; }
+
+ public String getAddress() { return address; }
+ public void setAddress(String address) { this.address = address; }
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt
new file mode 100644
index 000000000..35f17f5fd
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt
@@ -0,0 +1,44 @@
+/*
+ * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class AddressAction extends ActionSupport {
+
+ private Set addresses = new LinkedHashSet();
+
+ public Set getAddresses() { return addresses; }
+ public void setAddresses(Set addresses) { this.addresses = addresses; }
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ System.out.println(addresses);
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt
new file mode 100644
index 000000000..0a1b1aa38
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt
@@ -0,0 +1,55 @@
+/*
+ * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.struts2.util.StrutsTypeConverter;
+
+/**
+ * @version $Date$ $Id$
+ */
+public class EnumTypeConverter extends StrutsTypeConverter {
+
+ @Override
+ public Object convertFromString(Map context, String[] values, Class toClass) {
+ List result = new ArrayList();
+ for (int a=0; a< values.length; a++) {
+ Enum e = Enum.valueOf(OperationsEnum.class, values[a]);
+ if (e != null)
+ result.add(e);
+ }
+ return result;
+ }
+
+ @Override
+ public String convertToString(Map context, Object o) {
+ List l = (List) o;
+ String result ="<";
+ for (Iterator i = l.iterator(); i.hasNext(); ) {
+ result = result + "["+ i.next() +"]";
+ }
+ result = result+">";
+ return result;
+ }
+
+
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt
new file mode 100644
index 000000000..2db119448
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt
@@ -0,0 +1,30 @@
+/*
+ * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public enum OperationsEnum {
+ ADD,
+ MINUS,
+ DIVIDE,
+ MULTIPLY,
+ REMAINDER;
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt
new file mode 100644
index 000000000..ee2327ff3
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt
@@ -0,0 +1,53 @@
+/*
+ * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public class OperationsEnumAction extends ActionSupport {
+
+ private static final long serialVersionUID = -2229489704988870318L;
+
+ private List selectedOperations = new LinkedList();
+
+ public List getSelectedOperations() { return this.selectedOperations; }
+ public void setSelectedOperations(List selectedOperations) {
+ this.selectedOperations = selectedOperations;
+ }
+
+
+ public List getAvailableOperations() {
+ return Arrays.asList(OperationsEnum.values());
+ }
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt
new file mode 100644
index 000000000..621beafba
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt
@@ -0,0 +1,4 @@
+
+selectedOperations=org.apache.struts2.showcase.conversion.EnumTypeConverter
+Element_selectedOperations=org.apache.struts2.showcase.conversion.OperationsEnum
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt
new file mode 100644
index 000000000..2ce9e0fdb
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt
@@ -0,0 +1,34 @@
+/*
+ * $Id: AbstractDao.java 394498 2006-04-16 15:28:06Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+import java.io.Serializable;
+
+/**
+ *
+ */
+public class Person implements Serializable {
+ private String name;
+ private Integer age;
+
+ public void setName(String name) { this.name = name; }
+ public String getName() { return this.name; }
+
+ public void setAge(Integer age) { this.age = age; }
+ public Integer getAge() { return this.age; }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt
new file mode 100644
index 000000000..015fab018
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt
@@ -0,0 +1,43 @@
+/*
+ * $Id: AbstractDao.java 394498 2006-04-16 15:28:06Z tmjee $
+ *
+ * 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.showcase.conversion;
+
+import java.util.List;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ *
+ */
+public class PersonAction extends ActionSupport {
+
+ private List persons;
+
+ public List getPersons() { return persons; }
+ public void setPersons(List persons) { this.persons = persons; }
+
+
+
+ public String input() throws Exception {
+ return SUCCESS;
+ }
+
+ public String submit() throws Exception {
+ return SUCCESS;
+ }
+}
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp
new file mode 100644
index 000000000..2d028a869
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp
@@ -0,0 +1,48 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion - Set
+
+
+
+
+An example populating a Set of object (Address.java) into Struts' action (AddressAction.java)
+
+
+
+See the jsp code here.
+See the code for PersonAction.java here.
+See the code for Person.java here.
+
+
+
+
+
+
+
+
+
+
+ <%--
+ The following is how its done statically
+ --%>
+ <%--
+
+
+
+
+
+
+ --%>
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp
new file mode 100644
index 000000000..c01d6489b
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp
@@ -0,0 +1,31 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion - Tiger 5 Enum
+
+
+
+See the jsp code here.
+See the code for OperationsEnum.java here.
+See the code for OperationsEnumAction.java here.
+See the code for EnumTypeConverter.java here.
+See the properties for OperationsEnumAction-conversion.properties here.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp
new file mode 100644
index 000000000..8e9c54166
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp
@@ -0,0 +1,58 @@
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+Showcase - Conversion - Populate Object into Struts' action List
+
+
+
+
+An example populating a list of object (Person.java) into Struts' action (PersonAction.java)
+
+
+
+See the jsp code here.
+See the code for PersonAction.java here.
+See the code for Person.java here.
+
+
+
+
+
+
+
+ <%--
+ The following is done Dynamically
+ --%>
+
+
+
+
+
+
+
+ <%--
+ The following is done statically:-
+ --%>
+ <%--
+
+
+
+
+
+
+ --%>
+
+
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp
new file mode 100644
index 000000000..69f17c460
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp
@@ -0,0 +1,26 @@
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion
+
+
+
+
+
+
+ Populate into the Struts action class a List of Person.java Object
+
+
+
+ Populate into Struts action class a Set of Address.java Object
+
+
+
+ Populate into Struts action class a List of OperationEnum.java (Java5 Enum)
+
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp
new file mode 100644
index 000000000..2f1d4e346
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp
@@ -0,0 +1,15 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion - Set
+
+
+
+ ->
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp
new file mode 100644
index 000000000..c4b885903
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp
@@ -0,0 +1,17 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+ pageEncoding="UTF-8"%>
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion - Tiger 5 Enum
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp
new file mode 100644
index 000000000..b0b10e1b1
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp
@@ -0,0 +1,17 @@
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+
+Showcase - Conversion - Populate Object into Struts action List
+
+
+
+
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl
new file mode 100644
index 000000000..415233443
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl
@@ -0,0 +1,7 @@
+
+
+
+ This page shows a simple example of using a custom freemarker manager.
+ The custom freemarker manager put into freemarker model an util classed
+ under the name 'customFreemarkerManagerUtil'. so one could use
+
+
+
$ { customFreemarkerManagerUtil.getTodayDate() } - to get today's date
+
$ { customFreemarkerManagerUtil.todayDate } - to get today's date
+
$ { customFreemarkerManagerUtil.getTimeNow() } - to get the time now
+
$ { customFreemarkerManagerUtil.timeNow } - to get the time now
+
+
+ Today's Date = ${customFreemarkerManagerUtil.todayDate}
+ Time now = ${customFreemarkerManagerUtil.getTimeNow()}
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp
new file mode 100644
index 000000000..10b9932e7
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp
@@ -0,0 +1,23 @@
+
+<%@taglib prefix="s" uri="/struts-tags" %>
+
+
+
+ Showcase - Freemarker
+
+
+
+
+
+
+ Demo of usage of a Custom Freemarker Manager
+
+
+ Demo of Standard Struts Freemarker Tags
+
+
+
+
+
+
+
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl
new file mode 100644
index 000000000..1afc40913
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl
@@ -0,0 +1,4 @@
+<@s.form action="test">
+ <@s.textfield label="Name" name="name"/>
+ <@s.select label="Birth Month" headerValue="Select Month" list="months" />
+@s.form>
\ No newline at end of file
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/blank.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/blank.ftl
new file mode 100644
index 000000000..e69de29bb
diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl
new file mode 100644
index 000000000..379a2babf
--- /dev/null
+++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl
@@ -0,0 +1,241 @@
+
+
+
+ Showcase - Hangman
+ <@s.head theme="ajax" debug="false" />
+
+
+
+
+
+