Compare commits

...

2 Commits

Author SHA1 Message Date
Ted Nathan Husted 2c0a197cea =WW-1349 Tag r447072 as Struts 2.0.0
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_0@449438 13f79535-47bb-0310-9956-ffa450edef68
2006-09-24 17:18:08 +00:00
Ted Nathan Husted 5df2e63304 WW-1349 Tag r447072 as Struts 2.0.0
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_0@449437 13f79535-47bb-0310-9956-ffa450edef68
2006-09-24 17:17:49 +00:00
1995 changed files with 194355 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
name = struts-core
fullname = Struts
version = 2.0.0-SNAPSHOT
status = integration
cvs.tag = struts_2_0_0
+5
View File
@@ -0,0 +1,5 @@
ivy-configure=fr.jayasoft.ivy.ant.IvyConfigure
ivy-resolve=fr.jayasoft.ivy.ant.IvyResolve
ivy-retrieve=fr.jayasoft.ivy.ant.IvyRetrieve
ivy-publish=fr.jayasoft.ivy.ant.IvyPublish
ivy-report=fr.jayasoft.ivy.ant.IvyReport
+153
View File
@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="http://www.jayasoft.fr/org/ivyrep/ivy-doc.xsl"?>
<ivy-module version="1.0">
<info organisation="apache" module="struts2"
revision="2.0"
status="integration"
publication="20060323000000">
<license name="Apache" url="http://www.apache.org/licenses/LICENSE-2.0.txt"/>
<ivyauthor name="apache" url="http://www.apache.org/"/>
<description homepage="http://struts.apache.org/2.x/">
Struts 2 is a Java web-application development framework. It is built specifically with developer
productivity and code simplicity in mind. Struts 2 is built on
top of XWork, which provides a generic command pattern framework as well as an Inversion of Control
container. In addition to these features, Struts 2 provides
robust support for building reusable UI templates, such as form controls, UI themes, internationalization,
dynamic form parameter mapping to JavaBeans, robust
client and server side validation, and much more.
<br/>
</description>
</info>
<configurations>
<conf name="build" visibility="private"/>
<conf name="default"/>
<conf name="source"/>
<conf name="ajax"/>
<conf name="freemarker" deprecated="20060303000000"/>
<conf name="velocity"/>
<conf name="fileupload"/>
<conf name="fileupload-pell" deprecated="20050831000000"/>
<conf name="sitemesh"/>
<conf name="quickstart"/>
<conf name="jasperreports"/>
<conf name="jfree"/>
<conf name="xslt"/>
<conf name="portlet"/>
<conf name="spring"/>
<conf name="pico"/>
<conf name="plexus"/>
<conf name="xslt"/>
<conf name="tiger"/>
<conf name="cewolf"/>
<conf name="tiles"/>
</configurations>
<publications>
<artifact name="struts2" type="jar" conf="default"/>
</publications>
<dependencies>
<!-- build -->
<dependency org="mockobjects" name="mockobjects-core" rev="0.09" conf="build->*"/>
<dependency org="mockobjects" name="mockobjects-jdk1.3" rev="0.09" conf="build->*"/>
<dependency org="mockobjects" name="mockobjects-alt-jdk1.3" rev="0.09" conf="build->*"/>
<dependency org="mockobjects" name="mockobjects-alt-jdk1.3-j2ee1.3" rev="0.09" conf="build->*"/>
<dependency org="mockobjects" name="mockobjects-jdk1.3-j2ee1.3" rev="0.09" conf="build->*"/>
<dependency org="easymock" name="easymock" rev="2.0" conf="build->*"/>
<!--dependency org="easymock" name="easymockclassextension" rev="1.1" conf="build->*"/-->
<dependency org="clover" name="clover" rev="1.3.11" conf="build->*"/>
<dependency org="junit" name="junit" rev="3.8.1" conf="build->*"/>
<dependency org="jmock" name="jmock" rev="1.0.1" conf="build->*"/>
<dependency org="jmock" name="jmock-cglib" rev="1.0.1" conf="build->*"/>
<dependency org="servletapi" name="servletapi" rev="2.4" conf="build->*"/>
<dependency org="xdoclet" name="xdoclet" rev="1.2.3" conf="build->*"/>
<dependency org="xdoclet" name="xdoclet-web-module" rev="1.2.3" conf="build->*"/>
<dependency org="xjavadoc" name="xjavadoc" rev="1.1" conf="build->*"/>
<!-- default -->
<dependency org="opensymphony" name="xwork" rev="2.0+" conf="default->default"/>
<dependency org="apache" name="commons-logging" rev="1.0.4" conf="default->default"/>
<dependency org="opensymphony" name="xwork" rev="2.0+" conf="source->source"/>
<dependency org="freemarker" name="freemarker" rev="2.3.4" conf="default->default"/>
<!-- ajax -->
<dependency org="dwr" name="dwr" rev="1.1-beta-3" conf="ajax->*"/>
<!-- tiles -->
<dependency org="org.apache.struts.tiles" name="tiles-core" rev="0.2-SNAPSHOT" conf="tiles->default"/>
<dependency org="commons-digester" name="commons-digester" rev="1.7" conf="tiles->default"/>
<!-- velocity -->
<dependency org="apache" name="velocity" rev="1.4" conf="velocity->*"/>
<dependency org="apache" name="velocity-tools" rev="1.1" conf="velocity->view"/>
<dependency org="commons-collections" name="commons-collections" rev="2.1.1" conf="velocity->*"/>
<!-- fileupload -->
<dependency org="apache" name="commons-fileupload" rev="1.1" conf="fileupload->default"/>
<dependency org="apache" name="commons-io" rev="1.0" conf="fileupload->default" />
<!-- fileupload-pell -->
<dependency org="pell" name="multipartrequest" rev="1.19" conf="fileupload-pell->default"/>
<!-- sitemesh -->
<dependency org="opensymphony" name="sitemesh" rev="2.2.1" conf="sitemesh->default"/>
<!-- quickstart -->
<dependency org="jetty" name="org.mortbay.jetty" rev="5.1.4" conf="quickstart->default"/>
<dependency org="ant" name="ant" rev="1.6.5" conf="quickstart->default"/>
<dependency org="tomcat" name="jasper-runtime" rev="5.5.12" conf="quickstart->default"/>
<dependency org="tomcat" name="jasper-compiler" rev="5.5.12" conf="quickstart->default"/>
<dependency org="tomcat" name="jasper-compiler-jdt" rev="5.5.12" conf="quickstart->default"/>
<dependency org="commons-el" name="commons-el" rev="1.0" conf="quickstart->default"/>
<dependency org="commons-io" name="commons-io" rev="1.0" conf="quickstart->default"/>
<dependency org="commons-lang" name="commons-lang" rev="2.1" conf="quickstart->default"/>
<dependency org="servletapi" name="servletapi" rev="2.4" conf="quickstart->*" force="true"/>
<dependency org="jspapi" name="jsp-api" rev="2.0" conf="quickstart->*"/>
<dependency org="log4j" name="log4j" rev="1.2.9" conf="quickstart->*"/>
<dependency org="commons-collections" name="commons-collections" rev="2.1.1" conf="quickstart->default"/>
<dependency org="xstream" name="xstream" rev="1.1.2" conf="quickstart->default"/>
<!-- jasperreports -->
<dependency org="jasperreports" name="jasperreports" rev="1.2.0" conf="jasperreports->default"/>
<dependency org="itext" name="itext" rev="1.3.1" conf="jasperreports->default"/>
<dependency org="poi" name="poi" rev="2.5.1" conf="jasperreports->default"/>
<dependency org="commons-beanutils" name="commons-beanutils" rev="1.7.0" conf="jasperreports->default"/>
<dependency org="commons-digester" name="commons-digester" rev="1.7" conf="jasperreports->default"/>
<dependency org="commons-collections" name="commons-collections" rev="2.1.1" conf="jasperreports->default"/>
<!-- jfree -->
<dependency org="jfree" name="jcommon" rev="1.0.0" conf="jfree->default"/>
<dependency org="jfree" name="jfreechart" rev="1.0.0" conf="jfree->default"/>
<!-- xslt -->
<dependency org="jfree" name="jcommon" rev="1.0.0" conf="xslt->default"/>
<!-- portlet -->
<dependency org="portlet-api" name="portlet-api" rev="1.0" conf="portlet->default"/>
<!-- spring -->
<dependency org="opensymphony" name="xwork" rev="2.0+" conf="spring->spring"/>
<!-- pico -->
<dependency org="picocontainer" name="picocontainer" rev="1.2-RC-2" conf="pico->*"/>
<dependency org="picocontainer" name="picocontainer-gems" rev="1.2-RC-2" conf="pico->*"/>
<dependency org="nanocontainer" name="nanocontainer" rev="1.0-RC-3" conf="pico->*"/>
<dependency org="nanocontainer" name="nanocontainer-nanowar" rev="1.0-RC-3" conf="pico->*"/>
<!-- plexus -->
<dependency org="org.codehaus.plexus" name="plexus-container-default" rev="1.0-alpha-10-20060215.222714-5" conf="plexus->*"/>
<dependency org="org.codehaus.plexus" name="plexus-utils" rev="1.0.4" conf="plexus->*"/>
<dependency org="classworlds" name="classworlds" rev="1.1" conf="plexus->*"/>
<!-- xslt -->
<dependency org="w3c" name="dom" rev="3.0" conf="xslt->*"/>
<!-- tiger -->
<dependency org="opensymphony" name="xwork-tiger" rev="2.0+" conf="tiger->*"/>
<!-- cewolf -->
<dependency org="cewolf" name="cewolf" rev="0.12.0" conf="cewolf->*"/>
</dependencies>
</ivy-module>
+2
View File
@@ -0,0 +1,2 @@
ivy.retrieve.pattern = lib/[conf]/[artifact].[ext]
integration.repository = lib/integration
+30
View File
@@ -0,0 +1,30 @@
<ivyconf>
<properties file="ant-build/ivyconf.properties"/>
<conf defaultResolver="default" checkUpToDate="true"/>
<resolvers>
<chain name="default">
<filesystem name="integration" checkmodified="true">
<ivy pattern="${integration.repository}/[organisation]/[module]/ivy-[revision].xml"/>
<artifact pattern="${integration.repository}/[organisation]/[module]/[artifact]-[revision].[ext]"/>
</filesystem>
<url name="opensymphony" checkmodified="true">
<ivy pattern="http://ivyrep.opensymphony.com/[organisation]/[module]/ivy-[revision].xml"/>
<artifact
pattern="http://ivyrep.opensymphony.com/[organisation]/[module]/[artifact]-[revision].[type]"/>
</url>
<url name="contegix">
<ivy pattern="http://repository.contegix.com/ivyrep/[organisation]/[module]/ivy-[revision].xml"/>
<artifact
pattern="http://repository.contegix.com/ivyrep/[organisation]/[module]/[artifact]-[revision].[type]"/>
</url>
<ivyrep name="ivyrep"/>
<ibiblio name="contegix-maven" root="http://repository.contegix.com/maven"/>
<url name="maven">
<artifact pattern="http://www.ibiblio.org/maven/[organisation]/jars/[module]-[revision].[type]"/>
</url>
<!--url name="maven-mirror">
<artifact pattern="http://ibiblio.lsu.edu/main/pub/packages/maven/[organisation]/jars/[module]-[revision].[type]"/>
</url-->
</chain>
</resolvers>
</ivyconf>
+463
View File
@@ -0,0 +1,463 @@
<project name="common" default="jar" basedir=".">
<!--
OpenSymphony Common Build
=========================
TODO (Introduction)
Layout
=========================
TODO
Overriding
=========================
TODO
Example: <target name="compile" depends="myPreCompile,common.compile,myPostCompile"/>
-->
<!-- NOTE: this property is purely here to make a clear distinction in IDEA where the common build is -->
<property name="------common-properties-below------" value="Common properties below:"/>
<property name="compile.version" value="1.3"/>
<property name="test.compile.version" value="1.3"/>
<dirname property="common.dir" file="${ant.file.common}"/>
<property file="ant-build/build.properties"/>
<property file="ant-build/release.properties"/>
<property file="ant-build/ivyrep.properties"/>
<property name="lib" location="lib"/>
<property name="lib.core" value="${lib}/core"/>
<property name="lib.build" value="${lib}/build"/>
<property name="lib.optional" value="${lib}/optional"/>
<property name="src" location="core/src"/>
<property name="src.java" value="${src}/main/java"/>
<property name="src.test" value="${src}/test/java/"/>
<property name="src.resources" value="${src}/main/resources"/>
<property name="build" location="build"/>
<property name="build.test" value="${build}/test/java"/>
<property name="build.java-test" value="${build}/java-test"/>
<property name="build.java" value="${build}/java"/>
<property name="build.clover" value="${build}/clover"/>
<property name="dist" location="dist"/>
<property name="docs" location="docs"/>
<property name="docs.packages" value="org.apache.struts2.*"/>
<property name="jar.manifest" value="${common.dir}/EMPTY.MF"/>
<property name="jar.excludes" value=""/>
<property name="testcase" value="*"/>
<patternset id="src.test.pattern">
<exclude name="**/Abstract*.java"/>
<include name="**/${testcase}Test.java"/>
<include name="**/${testcase}TestCase.java"/>
</patternset>
<path id="cp">
<fileset dir="lib">
<include name="**/*.jar"/>
<include name="**/*.zip"/>
<exclude name="**/jalopy/**"/>
</fileset>
</path>
<path id="junit.cp">
<pathelement location="${build.java}"/>
<pathelement location="${build.test}"/>
<pathelement location="${src.test}/../resources"/>
<pathelement location="${build.java-test}"/>
<path refid="cp"/>
</path>
<path id="javadoc.path">
<path path="${src.java}"/>
</path>
<available property="junit.available" classname="junit.framework.TestCase"/>
<available property="clover.available" classname="org.apache.tools.ant.taskdefs.CloverCompilerAdapter"/>
<target name="init" depends="init-anthill, init-standalone">
<tstamp/>
</target>
<!-- in Anthill, the docs should be the Intranet copyDir -->
<target name="init-anthill" if="anthill.copyDir">
<property name="dist.docs" value="${anthill.copyDir}"/>
</target>
<!-- when building Standalone, the docs should be the normal place -->
<target name="init-standalone" unless="anthill.copyDir">
<property name="dist.docs" value="${dist}/docs"/>
</target>
<target name="junit-check" depends="init" unless="junit.available">
<fail message="Cannot run test cases. Please copy lib/build/junit.jar to ${ant.home}/lib"/>
</target>
<target name="clover-check" depends="init" unless="clover.available">
<fail message="Cannot run coverage tests. Please copy lib/build/clover.jar and lib/build/clover.license (if it exists) to ${ant.home}/lib"/>
</target>
<target name="clean">
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
<target name="precompile"/>
<macrodef name="compile">
<attribute name="srcdir"/>
<attribute name="destdir"/>
<attribute name="classpath" default=""/>
<attribute name="classpathref" default="cp"/>
<attribute name="includes" default="**/*.java"/>
<attribute name="excludes" default=""/>
<attribute name="source" default="${compile.version}"/>
<attribute name="target" default="${compile.version}"/>
<sequential>
<mkdir dir="@{destdir}"/>
<javac srcdir="@{srcdir}" destdir="@{destdir}" classpath="@{classpath}" classpathref="@{classpathref}"
debug="on" source="@{source}" target="@{target}" excludes="@{excludes}" />
<copy filtering="no" todir="@{destdir}">
<fileset dir="@{srcdir}">
<exclude name="**/*.java"/>
<exclude name="**/package.html"/>
</fileset>
</copy>
</sequential>
</macrodef>
<target name="compile" depends="init,precompile" description="compile project">
<compile srcdir="${src.java}" destdir="${build.java}" excludes="${optional.sources}" />
<copy filtering="no" todir="${build.java}" includeemptydirs="false">
<fileset dir="${src.resources}" >
<exclude name="java/*"/>
</fileset>
</copy>
</target>
<target name="jar" depends="compile" description="build the project jar file">
<mkdir dir="${build}"/>
<jar basedir="${build.java}" excludes="${jar.excludes}" jarfile="${build}/${name}-${version}.jar">
<manifest>
<attribute name="Implementation-Title" value="${fullname}"/>
<attribute name="Implementation-Version" value="${version}"/>
<attribute name="Implementation-Vendor" value="OpenSymphony"/>
</manifest>
</jar>
<jar basedir="${src.java}" jarfile="${build}/${name}-src-${version}.jar">
<manifest>
<attribute name="Implementation-Title" value="${fullname}"/>
<attribute name="Implementation-Version" value="${version}"/>
<attribute name="Implementation-Vendor" value="OpenSymphony"/>
</manifest>
</jar>
</target>
<target name="src-jar" depends="init" description="build a jar of the project source code">
<mkdir dir="${build}"/>
<jar basedir="${src.java}" jarfile="${build}/${name}-src-${version}.jar">
<manifest>
<attribute name="Implementation-Title" value="${fullname}"/>
<attribute name="Implementation-Version" value="${version}"/>
<attribute name="Implementation-Vendor" value="OpenSymphony"/>
</manifest>
</jar>
</target>
<target name="test-compile" unless="skip.tests">
<compile srcdir="${src.test}" destdir="${build.test}" classpath="${build.java}"
source="${test.compile.version}" target="${test.compile.version}" />
<taskdef resource="clovertasks"/>
<taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask"/>
<mkdir dir="${build.clover}"/>
<clover-setup initString="${build.clover}/coverage.db">
<statementContext name="logIsDebugEnabled" regexp="[\s]*if[\s]*\([\s]*(log|_log|LOG|_LOG)\.isDebugEnabled.*"/>
<statementContext name="logDebug" regexp="[\s]*(log|_log|LOG|_LOG)\.debug[\s]*\(.*"/>
<files>
<exclude name="${src.test}/**/*.java"/>
</files>
</clover-setup>
<!-- compile srcdir="${src.java}" destdir="${build.java-test}" / -->
</target>
<target name="test" depends="junit-check, clover-check, compile, test-compile" description="run tests"
unless="skip.tests">
<run-junit />
</target>
<macrodef name="run-junit">
<attribute name="classpathref" default="junit.cp" />
<attribute name="includes" default="**/${testcase}Test.java"/>
<attribute name="excludes" default=""/>
<sequential>
<mkdir dir="${dist.docs}/junit"/>
<junit haltonfailure="no" haltonerror="yes" fork="yes" forkmode="once" failureproperty="test.failure">
<jvmarg value="-Djava.awt.headless=true"/>
<jvmarg value="-Dorg.xml.sax.driver=org.apache.crimson.parser.XMLReaderImpl"/>
<classpath>
<path refid="@{classpathref}"/>
</classpath>
<formatter type="plain" useFile="false"/>
<formatter type="xml"/>
<batchtest todir="${dist.docs}/junit">
<fileset dir="${src.test}">
<exclude name="@{excludes}" />
<patternset refid="src.test.pattern"/>
<include name="@{includes}" />
</fileset>
</batchtest>
</junit>
</sequential>
</macrodef>
<target name="javadocs" description="generate javadocs">
<mkdir dir="${dist.docs}/api"/>
<javadoc sourcepathref="javadoc.path"
destdir="${dist.docs}/api"
packagenames="${docs.packages}"
classpathref="cp"
author="true"
version="true"
overview="${src.java}/overview.html"
windowTitle="${fullname} API - ${version}"
doctitle="${fullname} API (${version})"
footer="&lt;a href=&quot;http://www.opensymphony.com/${name}/&quot; target=&quot;_top&quot;&gt;${fullname} Project Page&lt;/a&gt;"
use="true"
verbose="false"
source="${compile.version}">
<tag name="s.tag" description="s.tag" enabled="false"/>
<tag name="s.tagattribute" description="s.tagattribute" enabled="false"/>
<link href="http://java.sun.com/j2se/${compile.version}/docs/api/"/>
<link href="http://java.sun.com/j2ee/${compile.version}/docs/api/"/>
</javadoc>
<!-- <copy overwrite="yes" file="${docs}/main.css" tofile="${docs}/api/stylesheet.css"/> -->
</target>
<target name="docs.impl">
<copy todir="${dist.docs}">
<fileset dir="${docs}"/>
</copy>
</target>
<target name="reports" depends="junit.report, clover.report, javadocs"
description="generate javadocs and junit and coverage reports"/>
<target name="docs" depends="reports, docs.impl"/>
<target name="clover.report" depends="test" description="generate coverage reports" unless="skip.tests">
<clover-report>
<current outfile="${dist.docs}/clover">
<format type="html" filter="logDebug,logIsDebugEnabled"/>
</current>
</clover-report>
<clover-log filter="logDebug,logIsDebugEnabled"/>
</target>
<target name="clover.historical" depends="clover.report" description="generate coverage historical reports"
unless="skip.tests">
<clover-historypoint historyDir="${build.clover}"/>
<clover-report>
<historical outfile="${dist.docs}/clover" historyDir="${build.clover}">
<format type="html" filter="logDebug,logIsDebugEnabled"/>
</historical>
</clover-report>
<clover-log filter="logDebug,logIsDebugEnabled"/>
</target>
<target name="junit.report" depends="test" description="generate junit reports" unless="skip.tests">
<junitreport todir="${dist.docs}/junit">
<fileset dir="${dist.docs}/junit">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${dist.docs}/junit"/>
</junitreport>
<!-- we fail here (instead of in the test target) so that the reports get generated first) -->
<fail if="test.failure" message="Tests did not all pass, failing!"/>
</target>
<target name="predist"/>
<target name="predist.zip"/>
<target name="dist" depends="jar, docs, predist" description="generate distribution zip file">
<copy todir="${dist}">
<fileset dir="${build}">
<include name="*.jar"/>
</fileset>
</copy>
<copy todir="${dist}/src">
<fileset dir="${src}"/>
</copy>
<mkdir dir="${dist}/lib"/>
<copy todir="${dist}/lib">
<fileset dir="${lib}">
<exclude name="**/no_dist/**"/>
</fileset>
</copy>
<copy todir="${dist}">
<fileset dir="${basedir}">
<include name="build.*"/>
<include name="osbuild.*"/>
<include name="ivy.*"/>
<include name="pom.*"/>
<include name="readme.txt"/>
<include name="license.txt"/>
</fileset>
</copy>
<!-- give a chance for project builds to do more before the zip is made. -->
<antcall target="predist.zip"/>
<zip destfile="${build}/${name}-${version}.zip">
<zipfileset prefix="${name}-${version}" dir="${dist}">
<exclude name="docs/clover/**/*"/>
<exclude name="docs/junit/**/*"/>
</zipfileset>
</zip>
<move file="${build}/${name}-${version}.zip" todir="${dist}" />
</target>
<target name="website" depends="javadocs, docs.impl"/>
<!-- =================================================================== -->
<!-- Fix carriage-return line feeds -->
<!-- =================================================================== -->
<target name="fixcrlf" description="Fixed CR/LF problems">
<echo>Running fixcrlf....</echo>
<fixcrlf eol="lf" srcdir="${basedir}/core/src"
includes="**/*.sh,
**/*.properties,
**/*.sql,
**/*.script,
**/*.java,
**/*.css,
**/*.js,
**/*.jsp,
**/*.ftl,
**/*.txt,
**/*.vm,
**/*.xml,
**/*.dtd,
**/*.xsl,
**/*.xslt,
**/*.html" />
<fixcrlf eol="lf" srcdir="${basedir}/apps"
includes="**/*.sh,
**/*.properties,
**/*.sql,
**/*.script,
**/*.java,
**/*.css,
**/*.js,
**/*.jsp,
**/*.ftl,
**/*.txt,
**/*.vm,
**/*.xml,
**/*.dtd,
**/*.xsl,
**/*.xslt,
**/*.html" />
</target>
<target name="ivyrep" depends="jar, ivyrep.impl"/>
<target name="ivyrep.impl">
<tstamp>
<format property="TIME" pattern="yyyyMMddHHmmss"/>
</tstamp>
<!-- make sure we have the latest -->
<echo>svn update</echo>
<exec executable="svn">
<arg value="update"/>
<arg line="${ivyrep.path}/opensymphony/${name}"/>
</exec>
<!-- delete the old timestamped builds and commit -->
<fileset dir="${ivyrep.path}/opensymphony/${name}" id="filesref">
<include name="${name}-${version}-*"/>
<include name="ivy-${version}-*"/>
</fileset>
<pathconvert property="files" refid="filesref" pathsep=" "/>
<echo>svn delete: ${files}</echo>
<exec executable="svn">
<arg value="delete"/>
<arg line="${files}"/>
</exec>
<!-- copy over the new build and source -->
<copy file="${build}/${name}-${version}.jar"
tofile="${ivyrep.path}/opensymphony/${name}/${name}-${version}-${TIME}.jar"/>
<copy file="${build}/${name}-src-${version}.jar"
tofile="${ivyrep.path}/opensymphony/${name}/${name}-src-${version}-${TIME}.jar"/>
<echo>svn add (jar)</echo>
<exec executable="svn">
<arg value="add"/>
<arg value="${ivyrep.path}/opensymphony/${name}/${name}-${version}-${TIME}.jar"/>
</exec>
<exec executable="svn">
<arg value="add"/>
<arg value="${ivyrep.path}/opensymphony/${name}/${name}-src-${version}-${TIME}.jar"/>
</exec>
<antcall target="ivyrep.copy-ivy"/>
<exec executable="svn">
<arg value="add"/>
<arg value="${ivyrep.path}/opensymphony/${name}/ivy-${version}-${TIME}.xml"/>
</exec>
<!-- now commit everything -->
<echo>svn commit</echo>
<exec executable="svn">
<arg value="commit"/>
<arg value="--username"/>
<arg value="${ivyrep.username}"/>
<arg value="--password"/>
<arg value="${ivyrep.password}"/>
<arg value="--non-interactive"/>
<arg value="-m"/>
<arg value="automatic commit"/>
<arg value="${ivyrep.path}/opensymphony/${name}"/>
</exec>
</target>
<target name="ivyrep.copy-ivy">
<!--
Note: Default implementation does not use Ivy itself to generate these files.
However, Ivy is really the best way to generate these, so projects that
do use Ivy should override this target like so:
<ivy-deliver deliverpattern="${ivyrep.path}/opensymphony/${name}/[artifact]-[revision].[ext]"
pubrevision="${version}-${TIME}" pubdate="${TIME}"/>
Over time as more projects adopt Ivy, this may become built in to the
common build.
-->
<copy file="ivy.xml" tofile="${ivyrep.path}/opensymphony/${name}/ivy-${version}-${TIME}.xml">
<filterset id="ivy.filter">
<filter token="VERSION" value="${version}-${TIME}"/>
<filter token="STATUS" value="${status}"/>
<filter token="PUBLICATION" value="${TIME}"/>
</filterset>
</copy>
</target>
</project>
+47
View File
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-api</artifactId>
<packaging>jar</packaging>
<name>Struts 2 API</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
<!-- has to be compile for StrutsTestCase, which is part of the base package so others can write unit tests -->
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<showPackage>false</showPackage>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,45 @@
package org.apache.struts2;
/**
* Default action interface. Provided purely for user convenience. Struts does not require actions to implement any
* interfaces. Actions need only implement a public, no argument method which returns {@code String}. If a user does
* not specify a method name, Struts defaults to {@code execute()}.
*
* <p>For example:
*
* <pre>
* static import ResultNames.*;
*
* public class MyAction <b>implements Action</b> {
*
* public String execute() {
* return SUCCESS;
* }
* }
* </pre>
*
* <p>is equivalent to:
*
* <pre>
* static import ResultNames.*;
*
* public class MyAction {
*
* public String execute() {
* return SUCCESS;
* }
* }
* </pre>
*
* @author crazybob@google.com (Bob Lee)
*/
public interface Action {
/**
* Executes this action.
*
* @return result name which matches a result name from the action mapping in the configuration file. See {@link
* ResultNames} for common suggestions.
*/
String execute();
}
@@ -0,0 +1,41 @@
package org.apache.struts2;
/**
* Implemented by actions which may need to record errors or messages.
*
* <pre>
* static import ResultNames.*;
*
* public class SetName implements MessageAware {
*
* Messages messages;
* String name;
*
* public String execute() {
* return SUCCESS;
* }
*
* public void setName(String name) {
* if ("".equals(name))
* messages.forField("name").addError("name.required");
*
* this.name = name;
* }
*
* public void setMessages(Messages messages) {
* this.messages = messages;
* }
* }
* </pre>
*
* @author crazybob@google.com (Bob Lee)
*/
public interface MessageAware {
/**
* Sets messages.
*
* @param messages messages
*/
void setMessages(Messages messages);
}
@@ -0,0 +1,196 @@
package org.apache.struts2;
import java.util.List;
import java.util.Set;
import java.util.Map;
/**
* Collection of messages. Supports nesting messages by field name.
*
* <p>Uses keys when adding instead of actual messages to decouple code from messages.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface Messages {
// TODO: Use Object[] for args instead of String[].
/**
* Message severity.
*/
public enum Severity {
/**
* Informational messages.
*/
INFO,
/**
* Warning messages.
*/
WARN,
/**
* Error messages.
*/
ERROR,
}
/**
* Gets nested messages for the given field.
*
* <p>Supports dot notation to represent nesting. For example:
*
* <pre>
* messages.forField("foo").forField("bar") == messages.forField("foo.bar")
* </pre>
*
* @param fieldName name of the field
* @return nested {@code Messages} for given field name
*/
Messages forField(String fieldName);
/**
* Gets map of field name to messages for that field.
*
* @return map of field name to {@code Messages}
*/
Map<String, Messages> forFields();
/**
* Adds informational message.
*
* @param key message key
* @see Severity.INFO
*/
void addInformation(String key);
/**
* Adds informational message.
*
* @param key message key
* @param arguments message arguments
* @see Severity.INFO
*/
void addInformation(String key, String... arguments);
/**
* Adds warning message.
*
* @param key message key
* @see Severity.WARN
*/
void addWarning(String key);
/**
* Adds warning message.
*
* @param key message key
* @param arguments message arguments
* @see Severity.WARN
*/
void addWarning(String key, String... arguments);
/**
* Adds error message.
*
* @param key message key
* @see Severity.ERROR
*/
void addError(String key);
/**
* Adds error message.
*
* @param key message key
* @param arguments message arguments
* @see Severity.ERROR
*/
void addError(String key, String... arguments);
/**
* Adds message.
*
* @param severity message severity
* @param key message key
*/
void add(Severity severity, String key);
/**
* Adds request-scoped message.
*
* @param severity message severity
* @param key message key
* @param arguments message arguments
*/
void add(Severity severity, String key, String... arguments);
/**
* Gets set of severities for which this {@code Messages} instance has messages. Not recursive.
*
* @return unmodifiable set of {@link Severity} sorted from least to most severe
*/
Set<Severity> getSeverities();
/**
* Gets message strings for the given severity. Not recursive.
*
* @param severity message severity
* @return unmodifiable list of messages
*/
List<String> forSeverity(Severity severity);
/**
* Gets error message strings for this {@code Messages} instance. Not recursive.
*
* @return unmodifiable list of messages
*/
List<String> getErrors();
/**
* Gets error message strings for this {@code Messages} instance. Not recursive.
*
* @return unmodifiable list of messages
*/
List<String> getWarnings();
/**
* Gets informational message strings for this {@code Messages} instance. Not recursive.
*
* @return unmodifiable list of messages
*/
List<String> getInformation();
/**
* Returns true if this or a nested {@code Messages} instance has error messages.
*
* @see Severity.ERROR
*/
boolean hasErrors();
/**
* Returns true if this or a nested {@code Messages} instance has warning messages.
*
* @see Severity.WARN
*/
boolean hasWarnings();
/**
* Returns true if this or a nested {@code Messages} instance has informational messages.
*
* @see Severity.INFO
*/
boolean hasInformation();
/**
* Returns true if this and all nested {@code Messages} instances have no messages.
*/
boolean isEmpty();
/**
* Returns true if this and all nested {@code Messages} instances have no messages for the given severity.
*
* @param severity message severity
*/
boolean isEmpty(Severity severity);
}
@@ -0,0 +1,36 @@
package org.apache.struts2;
/**
* Commonly used result names returned by action methods.
*
* @author crazybob@google.com (Bob Lee)
*/
public final class ResultNames {
private ResultNames() {}
/**
* The action executed successfully.
*/
public static final String SUCCESS = "success";
/**
* The action requires more input, i.e.&nbsp;a validation error occurred.
*/
public static final String INPUT = "input";
/**
* The action requires the user to log in before executing.
*/
public static final String LOGIN = "login";
/**
* The action execution failed irrecoverably.
*/
public static final String ERROR = "error";
/**
* The action executed successfully, but do not execute a result.
*/
public static final String NONE = "none";
}
@@ -0,0 +1,17 @@
package org.apache.struts2;
import org.apache.struts2.MessageAware;
/**
* Implemented by actions which wish to execute some validation logic before their action method. Useful for
* cross-field validations.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface Validatable extends MessageAware {
/**
* Validates input. Executes before action method.
*/
public void validate();
}
@@ -0,0 +1,18 @@
package org.apache.struts2.servlet;
import java.util.Map;
/**
* Implemented by actions which need direct access to the request parameters.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface ParameterAware {
/**
* Sets parameters.
*
* @param parameters map of parameter name to parameter values
*/
void setParameters(Map<String, String[]> parameters);
}
@@ -0,0 +1,18 @@
package org.apache.struts2.servlet;
import javax.servlet.http.HttpServletRequest;
/**
* Implemented by actions which need direct access to the servlet request.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface ServletRequestAware {
/**
* Sets the servlet request.
*
* @param request servlet request.
*/
void setServletRequest(HttpServletRequest request);
}
@@ -0,0 +1,18 @@
package org.apache.struts2.servlet;
import javax.servlet.http.HttpServletResponse;
/**
* Implemented by actions which need direct access to the servlet response.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface ServletResponseAware {
/**
* Sets the servlet response.
*
* @param response servlet response
*/
void setServletResponse(HttpServletResponse response);
}
@@ -0,0 +1,59 @@
package org.apache.struts2.spi;
import java.lang.reflect.Method;
/**
* Context of an action execution.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface ActionContext {
/**
* Gets action instance.
*/
Object getAction();
/**
* Gets action method.
*/
Method getMethod();
/**
* Gets action name.
*/
String getActionName();
/**
* Gets the path for the action's namespace.
*/
String getNamespacePath();
/**
* Gets the {@link Result} instance for the action.
*
* @return {@link Result} instance or {@code null} if we don't have a result yet.
*/
Result getResult();
/**
* Adds a result interceptor for the action. Enables executing code before and after a result, executing an
* alternate result, etc.
*/
void addResultInterceptor(Result interceptor);
/**
* Gets context of action which chained to us.
*
* @return context of previous action or {@code null} if this is the first action in the chain
*/
ActionContext getPrevious();
/**
* Gets context of action which this action chained to.
*
* @return context of next action or {@code null} if we haven't chained to another action yet or this is the last
* action in the chain.
*/
ActionContext getNext();
}
@@ -0,0 +1,16 @@
package org.apache.struts2.spi;
/**
* Intercepts an action request.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface Interceptor {
/**
* Intercepts an action request.
*
* @param requestContext current request context
*/
String intercept(RequestContext requestContext) throws Exception;
}
@@ -0,0 +1,101 @@
package org.apache.struts2.spi;
import org.apache.struts2.Messages;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Request context. A single request may span multiple actions with action chaining.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface RequestContext {
/**
* Gets context of the currently executing action.
*
* @return current action context
*/
ActionContext getActionContext();
/**
* Convenience method.&nbsp;Equivalent to {@code getActionContext().getAction()}.
*
* @return currently executing action
*/
Object getAction();
/**
* Gets map of request parameters.
*/
Map<String, String[]> getParameterMap();
/**
* Gets map of request attributes.
*/
Map<String, Object> getAttributeMap();
/**
* Gets map of session attributes.
*/
Map<String, Object> getSessionMap();
/**
* Gets map of application (servlet context) attributes.
*/
Map<String, Object> getApplicationMap();
/**
* Finds cookies with the given name,
*/
List<Cookie> findCookiesForName(String name);
/**
* Gets locale.
*/
Locale getLocale();
/**
* Sets locale. Stores the locale in the session for future requests.
*/
void setLocale(Locale locale);
/**
* Gets messages.
*/
Messages getMessages();
/**
* Gets the servlet request.
*/
HttpServletRequest getServletRequest();
/**
* Gets the servlet response.
*/
HttpServletResponse getServletResponse();
/**
* Gets the servlet context.
*/
ServletContext getServletContext();
/**
* Gets the value stack.
*/
ValueStack getValueStack();
/**
* Invokes the next interceptor or the action method if no more interceptors remain.
*
* @return result name
* @throws IllegalStateException if already invoked or called from the action
*/
String proceed() throws Exception;
}
@@ -0,0 +1,19 @@
package org.apache.struts2.spi;
import org.apache.struts2.spi.RequestContext;
/**
* Implemented by actions that need access to the current {@link org.apache.struts2.spi.RequestContext}. Use
* judiciously.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface RequestContextAware {
/**
* Sets {@link org.apache.struts2.spi.RequestContext}.
*
* @param requestContext
*/
void setRequestContext(RequestContext requestContext);
}
@@ -0,0 +1,18 @@
package org.apache.struts2.spi;
import org.apache.struts2.spi.RequestContext;
/**
* The result of an action request. Struts creates a new {@code Result} instance for each request.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface Result {
/**
* Executes result.
*
* @param requestContext
*/
void execute(RequestContext requestContext) throws Exception;
}
@@ -0,0 +1,93 @@
package org.apache.struts2.spi;
/**
* A central fixture of the Struts framework, the {@code ValueStack} is a stack which contains the actions
* which have executed in addition to other objects. Users can get and set values on the stack using expressions. The
* {@code ValueStack} will search down the stack starting with the most recent objects until it finds an object to
* which the expression can apply.
*
* @author crazybob@google.com (Bob Lee)
*/
public interface ValueStack extends Iterable<Object> {
/**
* Gets the top, most recent object from the stack without changing the stack.
*
* @return the top object
*/
Object peek();
/**
* Removes the top, most recent object from the stack.
*
* @return the top object
*/
Object pop();
/**
* Pushes an object onto the stack.
*
* @param o
*/
void push(Object o);
/**
* Creates a shallow copy of this stack.
*
* @return a new stack which contains the same objects as this one
*/
ValueStack clone();
/**
* Queries the stack. Starts with the top, most recent object. If the expression can apply to the object, this
* method returns the result of evaluating the expression. If the expression does not apply, this method moves
* down the stack to the next object and repeats. Returns {@code null} if the expression doesn't apply to any
* objects.
*
* @param expression
* @return the evaluation of the expression against the first applicable object in the stack
*/
Object get(String expression);
/**
* Queries the stack and converts the result to the specified type. Starts with the top, most recent object. If
* the expression can apply to the object, this method returns the result of evaluating the expression converted
* to the specified type. If the expression does not apply, this method moves down the stack to the next object
* and repeats. Returns {@code null} if the expression doesn't apply to any objects.
*
* @param expression
* @param asType the type to convert the result to
* @return the evaluation of the expression against the first applicable object in the stack converted to the
* specified type
*/
<T> T get(String expression, Class<T> asType);
/**
* Queries the stack and converts the result to a {@code String}. Starts with the top, most recent object. If the
* expression can apply to the object, this method returns the result of evaluating the expression converted to a
* {@code String}. If the expression does not apply, this method moves down the stack to the next object and
* repeats. Returns {@code null} if the expression doesn't apply to any objects.
*
* @param expression
* @return the evaluation of the expression against the first applicable object in the stack converted to a {@code
* String}
*/
String getString(String expression);
/**
* Sets a value on an object from the stack. This method starts at the top, most recent object. If the expression
* applies to that object, this methods sets the given value on that object using the expression and converting
* the type as necessary. If the expression does not apply, this method moves to the next object and repeats.
*
* @param expression
* @param value
*/
void set(String expression, Object value);
/**
* Returns the number of object on the stack.
*
* @return size of stack
*/
int size();
}
+10
View File
@@ -0,0 +1,10 @@
README.txt - blank
This is an "empty" application that you can deploy as the basis of your own
application.
For more on getting started with Struts, see
* http://cwiki.apache.org/WW/home.html
----------------------------------------------------------------------------
+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-blank</artifactId>
<packaging>war</packaging>
<name>Blank Webapp</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty6-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee_1.4_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,9 @@
package example;
import com.opensymphony.xwork2.ActionSupport;
/**
* Base Action class for the Tutorial package.
*/
public class ExampleSupport extends ActionSupport {
}
@@ -0,0 +1,40 @@
package example;
/**
* <code>Set welcome message.</code>
*/
public class HelloWorld extends ExampleSupport {
public String execute() throws Exception {
setMessage(getText(MESSAGE));
return SUCCESS;
}
/**
* Provide default valuie for Message property.
*/
public static final String MESSAGE = "HelloWorld.message";
/**
* Field for Message property.
*/
private String message;
/**
* Return Message property.
*
* @return Message property
*/
public String getMessage() {
return message;
}
/**
* Set Message property.
*
* @param message Text to display on HelloWorld page.
*/
public void setMessage(String message) {
this.message = message;
}
}
@@ -0,0 +1,38 @@
package example;
public class Login extends ExampleSupport {
public String execute() throws Exception {
if (isInvalid(getUsername())) return INPUT;
if (isInvalid(getPassword())) return INPUT;
return SUCCESS;
}
private boolean isInvalid(String value) {
return (value == null || value.length() == 0);
}
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -0,0 +1,24 @@
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="HelloWorld" class="example.HelloWorld">
<result>/example/HelloWorld.jsp</result>
</action>
<action name="Login!*" method="{1}" class="example.Login">
<result name="input">/example/Login.jsp</result>
<result type="redirect-action">Menu</result>
</action>
<action name="*" class="example.ExampleSupport">
<result>/example/{1}.jsp</result>
</action>
<!-- Add actions here -->
</package>
</struts>
@@ -0,0 +1,16 @@
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
</validators>
@@ -0,0 +1,5 @@
requiredstring = ${getText(fieldName)} is required.
password = Password
username = User Name
HelloWorld.message= Struts is up and running ...
Missing.message = This feature is under construction. Please try again in the next interation.
@@ -0,0 +1,2 @@
struts.devMode = true
struts.enable.DynamicMethodInvocation = false
@@ -0,0 +1,13 @@
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml"/>
<include file="example.xml"/>
<!-- Add packages here -->
</struts>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
<!-- add your spring beans here -->
</beans>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Struts Blank</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!--
This typically isn't required, as the taglib is included in struts-core.jar.
If you really need a taglib configuration within web.xml,
copy struts2-core/core/src/main/resources/META-INF/struts-tags.tld
to the WEB-INF directory as struts-tags.tld.
-->
<!--taglib>
<taglib-uri>/s</taglib-uri>
<taglib-location>/WEB-INF/struts-tags.tld</taglib-location>
</taglib-->
</web-app>
@@ -0,0 +1,11 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h2><s:property value="message"/></h2>
</body>
</html>
@@ -0,0 +1,15 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Logon</title>
</head>
<body>
<s:form action="Login">
<s:textfield label="%{getText('username')}" name="username"/>
<s:password label="%{getText('password')}" name="password" />
<s:submit/>
</s:form>
</body>
</html>
@@ -0,0 +1,3 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:include value="Missing.jsp"/>
@@ -0,0 +1,11 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Missing Feature</title></head>
<body>
<p>
<s:text name="Missing.message"/>
</p>
</body>
</html>
@@ -0,0 +1,35 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Welcome</title>
<link href="<s:url value="/css/examplecss"/>" rel="stylesheet"
type="text/css"/>
</head>
<body>
<h3>Commands</h3>
<ul>
<li><a href="<s:url action="Register"/>">Register</a></li>
<li><a href="<s:url action="Login!input"/>">Sign On</a></li>
</ul>
<h3>Languages</h3>
<ul>
<li>
<s:url id="url" action="Welcome">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{url}">English</s:a>
</li>
<li>
<s:url id="url" action="Welcome">
<s:param name="request_locale">ja</s:param>
</s:url>
<s:a href="%{url}">Japanese</s:a>
</li>
</ul>
</body>
</html>
@@ -0,0 +1,10 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=example/Welcome.action">
</head>
<body>
<p>Loading ...</p>
</body>
</html>
@@ -0,0 +1,75 @@
package example;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.XWorkTestCase;
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;
public class ConfigTest extends XWorkTestCase {
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);
}
}
@@ -0,0 +1,16 @@
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()));
}
}
@@ -0,0 +1,36 @@
package example;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import java.util.Map;
import java.util.Collection;
import java.util.List;
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.");
}
}
+18
View File
@@ -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/
----------------------------------------------------------------------------
+49
View File
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-mailreader</artifactId>
<packaging>war</packaging>
<name>Starter Webapp</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${pom.groupId}</groupId>
<artifactId>struts-mailreader-dao</artifactId>
<version>1.3.5-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty6-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee_1.4_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
<!-- add your spring beans here -->
</beans>
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="mailreader-default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="authentication"
class="mailreader2.AuthenticationInterceptor"/>
<interceptor-stack name="user" >
<interceptor-ref name="authentication" />
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
<interceptor-stack name="user-submit" >
<interceptor-ref name="token-session" />
<interceptor-ref name="user"/>
</interceptor-stack>
<interceptor-stack name="guest" >
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="user"/>
<global-results>
<result name="error">/pages/Error.jsp</result>
<result name="invalid.token">/pages/Error.jsp</result>
<result name="login" type="redirect-action">Login!input</result>
</global-results>
<global-exception-mappings>
<exception-mapping
result="error"
exception="java.lang.Throwable"/>
</global-exception-mappings>
</package>
</struts>
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="mailreader-support" namespace="/" extends="mailreader-default">
<action name="Tour">
<result>/tour.html</result>
<interceptor-ref name="guest"/>
</action>
<action name="Welcome" class="mailreader2.Welcome">
<result>/Welcome.jsp</result>
<interceptor-ref name="guest"/>
</action>
<action name="Logout" class="mailreader2.Logout">
<result type="redirect-action">Welcome</result>
</action>
<action name="Login!*" method="{1}" class="mailreader2.Login">
<result name="input">/Login.jsp</result>
<result name="cancel" type="redirect-action">Welcome</result>
<result type="redirect-action">MainMenu</result>
<result name="expired" type="chain">ChangePassword</result>
<exception-mapping
exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
result="expired"/>
<interceptor-ref name="guest"/>
</action>
<action name="Registration!*" method="{1}" class="mailreader2.Registration">
<result name="input">/Registration.jsp</result>
<result type="redirect-action">MainMenu</result>
<interceptor-ref name="guest"/>
</action>
</package>
<package name="subscription" namespace="/" extends="mailreader-support">
<global-results>
<result name="input">/Subscription.jsp</result>
<result type="redirect-action">Registration!input</result>
</global-results>
<action name="Subscription!save" method="save" class="mailreader2.Subscription">
<interceptor-ref name="user-submit" />
</action>
<action name="Subscription!*" method="{1}" class="mailreader2.Subscription" />
</package>
<package name="wildcard" namespace="/" extends="mailreader-support">
<action name="*" class="mailreader2.MailreaderSupport">
<result>/{1}.jsp</result>
</action>
</package>
</struts>
@@ -0,0 +1,231 @@
/*
* Copyright 1999-2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id$
*/
package mailreader2;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.io.*;
/**
* <p><code>ServletContextListener</code> that initializes and finalizes the
* persistent storage of User and Subscription information for the Struts
* Demonstration Application, using an in-memory database backed by an XML
* file.</p>
* <p/>
* <p><strong>IMPLEMENTATION WARNING</strong> - If this web application is run
* from a WAR file, or in another environment where reading and writing of the
* web application resource is impossible, the initial contents will be copied
* to a file in the web application temporary directory provided by the
* container. This is for demonstration purposes only - you should
* <strong>NOT</strong> assume that files written here will survive a restart
* of your servlet container.</p>
* <p/>
* <p>This class was borrowed from the Shale Mailreader. Changes were:</p>
* <p/>
* <ul>
* <p/>
* <li>Path to database.xml (under classes here). </li>
* <p/>
* <li>Class to store protocol list (an array here). </li>
* <p/>
* </ul>
* <p>
* DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring.
* </p>
*/
public final class ApplicationListener implements ServletContextListener {
// ------------------------------------------------------ Manifest Constants
/**
* <p>Appication scope attribute key under which the in-memory version of
* our database is stored.</p>
*/
public static final String DATABASE_KEY = "database";
/**
* <p>Application scope attribute key under which the valid selection
* items for the protocol property is stored.</p>
*/
public static final String PROTOCOLS_KEY = "protocols";
// ------------------------------------------------------ Instance Variables
/**
* <p>The <code>ServletContext</code> for this web application.</p>
*/
private ServletContext context = null;
/**
* The {@link MemoryUserDatabase} object we construct and make available.
*/
private MemoryUserDatabase database = null;
/**
* <p>Logging output for this plug in instance.</p>
*/
private Log log = LogFactory.getLog(this.getClass());
// ------------------------------------------------------------- Properties
/**
* <p>The web application resource path of our persistent database storage
* file.</p>
*/
private String pathname = "/WEB-INF/classes/database.xml";
/**
* <p>Return the application resource path to the database.</p>
*
* @return application resource path path to the database
*/
public String getPathname() {
return (this.pathname);
}
/**
* <p>Set the application resource path to the database.</p>
*
* @param pathname to the database
*/
public void setPathname(String pathname) {
this.pathname = pathname;
}
// ------------------------------------------ ServletContextListener Methods
/**
* <p>Gracefully shut down this database, releasing any resources that
* were allocated at initialization.</p>
*
* @param event ServletContextEvent to process
*/
public void contextDestroyed(ServletContextEvent event) {
log.info("Finalizing memory database plug in");
if (database != null) {
try {
database.close();
} catch (Exception e) {
log.error("Closing memory database", e);
}
}
context.removeAttribute(DATABASE_KEY);
context.removeAttribute(PROTOCOLS_KEY);
database = null;
context = null;
}
/**
* <p>Initialize and load our initial database from persistent
* storage.</p>
*
* @param event The context initialization event
*/
public void contextInitialized(ServletContextEvent event) {
log.info("Initializing memory database plug in from '" +
pathname + "'");
// Remember our associated ServletContext
this.context = event.getServletContext();
// Construct a new database and make it available
database = new MemoryUserDatabase();
try {
String path = calculatePath();
if (log.isDebugEnabled()) {
log.debug(" Loading database from '" + path + "'");
}
database.setPathname(path);
database.open();
} catch (Exception e) {
log.error("Opening memory database", e);
throw new IllegalStateException("Cannot load database from '" +
pathname + "': " + e);
}
context.setAttribute(DATABASE_KEY, database);
}
// -------------------------------------------------------- Private Methods
/**
* <p>Calculate and return an absolute pathname to the XML file to contain
* our persistent storage information.</p>
*
* @throws Exception if an input/output error occurs
*/
private String calculatePath() throws Exception {
// Can we access the database via file I/O?
String path = context.getRealPath(pathname);
if (path != null) {
return (path);
}
// Does a copy of this file already exist in our temporary directory
File dir = (File)
context.getAttribute("javax.servlet.context.tempdir");
File file = new File(dir, "struts-example-database.xml");
if (file.exists()) {
return (file.getAbsolutePath());
}
// Copy the static resource to a temporary file and return its path
InputStream is =
context.getResourceAsStream(pathname);
BufferedInputStream bis = new BufferedInputStream(is, 1024);
FileOutputStream os =
new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os, 1024);
byte buffer[] = new byte[1024];
while (true) {
int n = bis.read(buffer);
if (n <= 0) {
break;
}
bos.write(buffer, 0, n);
}
bos.close();
bis.close();
return (file.getAbsolutePath());
}
}
@@ -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();
}
}
}
@@ -0,0 +1,125 @@
/*
* $Id$
*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mailreader2;
/**
* <p> Manifest constants for the MailReader application. </p>
*/
public final class Constants {
// --- Tokens ----
/**
* <p> The token representing a "cancel" request. </p>
*/
public static final String CANCEL = "cancel";
/**
* <p> The token representing a "create" task. </p>
*/
public static final String CREATE = "Create";
/**
* <p> The application scope attribute under which our user database is
* stored. </p>
*/
public static final String DATABASE_KEY = "database";
/**
* <p> The token representing a "edit" task. </p>
*/
public static final String DELETE = "Delete";
/**
* <p> The token representing a "edit" task. </p>
*/
public static final String EDIT = "Edit";
/**
* <p> The package name for this application. </p>
*/
public static final String PACKAGE = "org.apache.struts.apps.mailreader";
/**
* <p> The session scope attribute under which the Subscription object
* currently selected by our logged-in User is stored. </p>
*/
public static final String SUBSCRIPTION_KEY = "subscription";
/**
* <p> The session scope attribute under which the User object for the
* currently logged in user is stored. </p>
*/
public static final String USER_KEY = "user";
/**
* <p>The token representing the "Host" property.
*/
public static final String HOST = "host";
// ---- Error Messages ----
/**
* <p>
* A static message in case message resource is not loaded.
* </p>
*/
public static final String ERROR_MESSAGES_NOT_LOADED =
"ERROR: Message resources not loaded -- check servlet container logs for error messages.";
/**
* <p>
* A static message in case database resource is not loaded.
* <p>
*/
public static final String ERROR_DATABASE_NOT_LOADED =
"ERROR: User database not loaded -- check servlet container logs for error messages.";
/**
* <p>
* A standard key from the message resources file, to test if it is available.
* <p>
*/
public static final String ERROR_DATABASE_MISSING = "error.database.missing";
/**
* <P>
* A "magic" username to trigger an ExpiredPasswordException for testing.
*</p>
*/
public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException";
/**
* <p>
* Name of field to associate with authentification errors.
* <p>
*/
public static final String PASSWORD_MISMATCH_FIELD = "password";
// ---- Log Messages ----
/**
* <p> Message to log if saving a user fails. </p>
*/
public static final String LOG_DATABASE_SAVE_ERROR =
" Unexpected error when saving User: ";
}
@@ -0,0 +1,45 @@
/*
* $Id$
*
* Copyright 2000-2004 Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mailreader2;
import org.apache.struts.apps.mailreader.dao.User;
import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException;
/**
* <p> Validate a user login. </p>
*/
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;
}
}
@@ -0,0 +1,14 @@
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="error.username.required"/>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="error.password.required"/>
</field-validator>
</field>
</validators>
@@ -0,0 +1,32 @@
/*
* $Id$
*
* Copyright 2000-2004 Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mailreader2;
/**
* <p> Log user out of the current session. </p>
*/
public class Logout extends MailreaderSupport {
public String execute() {
setUser(null);
return SUCCESS;
}
}
@@ -0,0 +1,559 @@
/*
* $Id$
*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package 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 org.springframework.beans.BeanUtils;
import java.util.Map;
/**
* <p> Base Action for MailreaderSupport application. </p>
* <p/>
* <p> Note that this class does NOT implement model driven because of the way
* the pre-existing model is designed. The MailReader DAO includes immutable
* fields that can only be set on construction, and some objects do not have a
* default construction. One approach would be to mirror all the DAO
* properties on the Actions. As an alternative, this implementations uses the
* DAO properties where possible, and uses local Action properties only as
* needed. To create new objects, a blank temporary object is constructed, and
* the page uses a mix of local Action properties and DAO properties. When the
* new object is to be saved, the local Action properties are used to create
* the object using the DAO factory methods, the input values are copied from
* the temporary object, and the new object is saved. It's kludge, but it
* avoids creating unnecessary local properties. Pick your poison.</p>
*/
public class MailreaderSupport extends ActionSupport
implements SessionAware, ApplicationAware {
/**
* Return CANCEL so apropriate result can be selected.
* @return "cancel" so apropriate result can be selected.
*/
public String cancel() {
return Constants.CANCEL;
}
// ---- ApplicationAware ----
/**
* <p>Field to store application context or its proxy.</p>
* <p/>
* <p>The application context lasts for the life of the application. A
* reference to the database is stored in the application context at
* startup.</p>
*/
private Map application;
/**
* <p>Store a new application context.</p>
*
* @param value A Map representing application state
*/
public void setApplication(Map value) {
application = value;
}
/**
* <p>Provide application context.</p>
*/
public Map getApplication() {
return application;
}
// ---- SessionAware ----
/**
* <p>Field to store session context, or its proxy.</p>
*/
private Map session;
/**
* <p>Store a new session context.</p>
*
* @param value A Map representing session state
*/
public void setSession(Map value) {
session = value;
}
/**
* <p>Provide session context.</p>
*
* @return session context
*/
public Map getSession() {
return session;
}
// ---- Task property (utilized by UI) ----
/**
* <p>Field to store workflow task.</p>
* <p/>
* <p>The Task is used to track the state of the CRUD workflows. It can be
* set to Constant.CREATE, Constant.EDIT, or Constant.DELETE as
* needed.</p>
*/
private String task = null;
/**
* <p>Provide worklow task.</p>
*
* @return Returns the task.
*/
public String getTask() {
return task;
}
/**
* <p>Store new workflow task.</p>
*
* @param value The task to set.
*/
public void setTask(String value) {
task = value;
}
// ---- Token property (utilized by UI) ----
/**
* <p>Field to store double-submit guard.</p>
*/
private String token = null;
/**
* <p>Provide Token.</p>
*
* @return Returns the token.
*/
public String getToken() {
return token;
}
/**
* <p>Store new Token.</p>
*
* @param value The token to set.
*/
public void setToken(String value) {
token = value;
}
// ---- Host property ----
/**
* <p>Field to store Subscription host.</p>
* <p/>
* <p> The host is an immutable property of the Subscrtion DAP object, so
* we need to store it locally until we are ready to create the
* Subscription. </p>
*/
private String host;
/**
* <p>Provide tSubscription host.</p>
*
* @return host property
*/
public String getHost() {
return host;
}
/**
* <p>Store new Subscription host.</p>
*
* @param value
*/
public void setHost(String value) {
host = value;
}
// ---- Password property ----
/**
* <p>Field to store User password property.</p>
* <p/>
* <p>The User DAO object password proerty is immutable, so we store it
* locally until we are ready to create the object.</p>
*/
private String password = null;
/**
* <p>Provide User password</p>
*
* @return Returns the password.
*/
public String getPassword() {
return password;
}
/**
* <p>Store new User Password</p>
*
* @param value The password to set.
*/
public void setPassword(String value) {
password = value;
}
// ---- Password2 property (confirmation) ----
/**
* <p>Field to store the User password confirmation.</p>
* <p/>
* <p>When a User object is created, we ask the client to enter the
* password twice, to help ensure the password is being typed
* correctly.</p>
*/
private String password2 = null;
/**
* <p>Provide the User password confirmation.</p>
*
* @return Returns the confirmationpassword.
*/
public String getPassword2() {
return password2;
}
/**
* <p>Store a new User password confirmation.</p>
*
* @param value The confirmation password to set.
*/
public void setPassword2(String value) {
password2 = value;
}
// ---- Username property ----
/**
* <p>Field to store User username.</p>
* <p/>
* <p>The User DAO object password proerty is immutable, so we store it
* locally until we are ready to create the object.</p>
*/
private String username = null;
/**
* <p>Provide User username.</p>
*
* @return Returns the User username.
*/
public String getUsername() {
return username;
}
/**
* <p>Store new User username</p>
*
* @param value The username to set.
*/
public void setUsername(String value) {
username = value;
}
// ---- Database property ----
/**
* <p>Provide reference to UserDatabase, or null if the database is not
* available. </p>
*
* @return a reference to the UserDatabase or null if the database is not
* available
*/
public UserDatabase getDatabase() {
Object db = getApplication().get(Constants.DATABASE_KEY);
if (db == null) {
this.addActionError(getText("error.database.missing"));
}
return (UserDatabase) db;
}
/**
* <p>Store a new reference to UserDatabase</p>
*
* @param database
*/
public void setDatabase(UserDatabase database) {
getApplication().put(Constants.DATABASE_KEY, database);
}
// ---- User property ----
/**
* <p>Provide reference to User object for authenticated user.</p>
*
* @return User object for authenticated user.
*/
public User getUser() {
return (User) getSession().get(Constants.USER_KEY);
}
/**
* <p>Store new reference to User Object.</p>
*
* @param user User object for authenticated user
*/
public void setUser(User user) {
getSession().put(Constants.USER_KEY, user);
}
/**
* <p>Obtain User object from database, or return null if the credentials
* are not found or invalid.</p>
*
* @param username User username
* @param password User password
* @return User object or null if not found
* @throws ExpiredPasswordException
*/
public User findUser(String username, String password)
throws ExpiredPasswordException {
// FIXME: Stupid testing hack to compensate for inadequate DAO layer
if (Constants.EXPIRED_PASSWORD_EXCEPTION.equals(username)) {
throw new ExpiredPasswordException(Constants.EXPIRED_PASSWORD_EXCEPTION);
}
User user = getDatabase().findUser(username);
if ((user != null) && !user.getPassword().equals(password)) {
user = null;
}
if (user == null) {
this.addFieldError(Constants.PASSWORD_MISMATCH_FIELD,
getText("error.password.mismatch"));
}
return user;
}
/**
* <p><code>Log</code> instance for this application. </p>
*/
protected Log log = LogFactory.getLog(Constants.PACKAGE);
/**
* <p> Persist the User object, including subscriptions, to the database.
* </p>
*
* @throws java.lang.Exception on database error
*/
public void saveUser() throws Exception {
try {
getDatabase().save();
} catch (Exception e) {
String message = Constants.LOG_DATABASE_SAVE_ERROR + getUser()
.getUsername();
log.error(message, e);
throw new Exception(message, e);
}
}
public void createInputUser() {
User user = new MemoryUser(null, null);
setUser(user);
}
/**
* <p> Verify input for creating a new user, create the user, and process
* the login. </p>
*
* @return A new User and empty Errors if create succeeds, or null and
* Errors if create fails
*/
public User createUser(String username, String password) {
UserDatabase database = getDatabase();
User user;
try {
user = database.findUser(username);
}
catch (ExpiredPasswordException e) {
user = getUser(); // Just so that it is not null
}
if (user != null) {
this.addFieldError("username", "error.username.unique");
return null;
}
return database.createUser(username);
}
// Since user.username is immutable, we have to use some local properties
/**
* <p>Use the current User object to create a new User object, and make
* the new User object the authenticated user.</p>
* <p/>
* <p>The "current" User object is usually a temporary object being used
* to capture input.</p>
*
* @param _username User username
* @param _password User password
*/
public void copyUser(String _username, String _password) {
User input = getUser();
input.setPassword(_password);
User user = createUser(_username, _password);
if (null != user) {
BeanUtils.copyProperties(input,user);
setUser(user);
}
}
// ---- Subscription property ----
/**
* <p>Obtain the cached Subscription object, if any. </p>
*
* @return Cached Subscription object or null
*/
public Subscription getSubscription() {
return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY);
}
/**
* <p>Store new User Subscription.</p>
*
* @param subscription
*/
public void setSubscription(Subscription subscription) {
getSession().put(Constants.SUBSCRIPTION_KEY, subscription);
}
/**
* <p> Obtain User Subscription object for the given host, or return null
* if not found. </p>
*
* <p>It would be possible for this code to throw a NullPointerException,
* but the ExceptionHandler in the xwork.xml will catch that for us.</p>
*
* @return The matching Subscription or null
*/
public Subscription findSubscription(String host) {
Subscription subscription;
subscription = getUser().findSubscription(host);
return subscription;
}
/**
* <p>Obtain uSER Subscription for the local Host property.</p>
* <p/>
* <p>Usually, the host property will be set from the client request,
* because it was embedded in a link to the Subcription action.
*
* @return Subscription or null if not found
*/
public Subscription findSubscription() {
return findSubscription(getHost());
}
/**
* <p>Provide a "temporary" User Subscription object that can be used to
* capture input values.</p>
*/
public void createInputSubscription() {
Subscription sub = new MemorySubscription(getUser(), null);
setSubscription(sub);
setHost(sub.getHost());
}
/**
* <p>Provide new User Subscription object for the given host, or null if
* the host is not unique.</p>
*
* @param host
* @return New User Subscription object or null
*/
public Subscription createSubscription(String host) {
Subscription sub;
sub = findSubscription(host);
if (null != sub) {
// FIXME - localization - "error.host.unique")
addFieldError(Constants.HOST,"That hostname is already defined");
return null;
}
return getUser().createSubscription(host);
}
/**
* <p>Create a new Subscription from the current Subscription object,
* making the new Subscription the current Subscription. </p>
* <p/>
* <p>Usually, the "current" Subscription is a temporary object being used
* to capture input values.</p>
*
* @param host
*/
public void copySubscription(String host) {
Subscription input = getSubscription();
Subscription sub = createSubscription(host);
if (null != sub) {
BeanUtils.copyProperties(input, sub);
setSubscription(sub);
setHost(sub.getHost());
}
}
/**
* <p>Delete the current Subscription object from the database.</p>
*/
public void removeSubscription() {
getUser().removeSubscription(getSubscription());
getSession().remove(Constants.SUBSCRIPTION_KEY);
}
/**
* <p>Provide MailServer Host for current User Subscription.</p>
*
* @return MailServer Host for current User Subscription
*/
public String getSubscriptionHost() {
Subscription sub = getSubscription();
if (null == sub) {
return null;
}
return sub.getHost();
}
}
@@ -0,0 +1,93 @@
button.cancel=Cancel
button.confirm=Confirm
button.doSubmit=DO_SUBMIT
button.doReset=DO_RESULT
button.doCancel=org.apache.struts.taglib.html.CANCEL
button.reset=Reset
button.save=Save
change.message=Your password has expired. Please ask the system administrator to change it.
change.try=Try Again
change.title=Password Has Expired
database.load=Cannot load database from {0}
error.database.missing=User database is missing, cannot validate 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=</ul><hr>
errors.header=<h3><font color="red">Validation Error</font></h3><p>You must correct the following error(s) before proceeding:</p><ul>
errors.prefix=<li>
errors.suffix=</li>
errors.ioException=I/O exception rendering error messages: {0}
expired.password=User Password has expired for {0}
heading.autoConnect=Auto
heading.subscriptions=Current Subscriptions
heading.host=Host Name
heading.user=User Name
heading.type=Server Type
heading.action=Action
index.heading=MailReader Demonstration Application Options
index.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.
autoConnect=Auto Connect
fromAddress=From Address
fullName=Full Name
mailHostname=Mail Server
mailPassword=Mail Password
mailServerType=Server Type
mailUsername=Mail Username
password=Password
password2=(Repeat) Password
replyToAddress=Reply To Address
username=Username
registration.addSubscription=Add
registration.deleteSubscription=Delete
registration.editSubscription=Edit
registration.title.create=Register for the MailReader Demonstration Application
registration.title.edit=Edit Registration for the MailReader Demonstration Application
subscription.title.create=Create New Mail Subscription
subscription.title.delete=Delete Existing Mail Subscription
subscription.title.edit=Edit Existing Mail Subscription
# Standard error messages for validator framework checks
errors.required=${getText(fieldName)} is required.
errors.minlength=${getText(fieldName)} cannot be less than {1} characters.
errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters.
errors.invalid=${getText(fieldName)} is invalid.
errors.byte=${getText(fieldName)} must be an byte.
errors.short=${getText(fieldName)} must be an short.
errors.integer=${getText(fieldName)} must be an integer.
errors.long=${getText(fieldName)} must be an long.
errors.float=${getText(fieldName)} must be an float.
errors.double=${getText(fieldName)} must be an double.
errors.date=${getText(fieldName)} is not a date.
errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}.
errors.creditcard=${getText(fieldName)} is not a valid credit card number.
errors.email=${getText(fieldName)} is an invalid e-mail address.
errors.literal=${getText(fieldName)}
@@ -0,0 +1,89 @@
button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
button.confirm=\u78ba\u8a8d
button.reset=\u30ea\u30bb\u30c3\u30c8
button.save=\u4fdd\u5b58
change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044
change.try=\u518D\u8A66\u884C
change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c
database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093
error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093
error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093
error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059
error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059
error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093
struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093
error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093
error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044
error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
errors.footer=</ul><hr>
errors.header=<h3><font color="red">\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc</font></h3><p>\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:</p><ul>
errors.prefix=<li>
errors.suffix=</li>
errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0}
expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F
heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a
heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831
heading.host=\u30db\u30b9\u30c8\u540d
heading.user=\u30e6\u30fc\u30b6\u540d
heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
heading.action=\u64cd\u4f5c
index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3
index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev)
index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b
linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0}
linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
linkUser.io=I/O\u30a8\u30e9\u30fc: {0}
linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3
mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
mainMenu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5
mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6
mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc
option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb
option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb
# prompt.
autoConnect=\u81ea\u52d5\u63a5\u7d9a
fromAddress=From\u30a2\u30c9\u30ec\u30b9
fullName=\u30d5\u30eb\u30cd\u30fc\u30e0
mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0
mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9
mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7
mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d
.password=\u30d1\u30b9\u30ef\u30fc\u30c9
password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528)
replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9
username=\u30e6\u30fc\u30b6\u540d
registration.addSubscription=\u65b0\u898f\u4f5c\u6210
registration.deleteSubscription=\u524a\u9664
registration.editSubscription=\u7de8\u96c6
registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332
registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6
subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210
subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664
subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6
# Standard error messages for validator framework checks
errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
@@ -0,0 +1,89 @@
button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c
button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c
button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
change.message=Your password has expired. Please ask the system administrator to change it.
change.try=Try Again
change.title=Password Has Expired
database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0}
error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e.
error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'.
error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f.
error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.
error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
error.password.expired=Your password has expired for username {0}
error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c.
error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.
error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.
error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430.
error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435.
struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.
error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3'
error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f
error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f.
errors.footer=</ul><hr>
errors.header=<h3><font color="red">\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445</font></h3><p>\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:</p><ul>
errors.prefix=<li>
errors.suffix=</li>
errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0}
expired.password=User Password has expired for {0}
heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438
heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438
heading.host=\u0421\u0435\u0440\u0432\u0435\u0440
heading.user=\u0418\u043c\u044f
heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430
heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c
index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f
index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev)
index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b'
linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0}
linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0}
linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.
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.
@@ -0,0 +1,28 @@
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="password">
<field-validator type="requiredstring">
<message key="error.password.required"/>
</field-validator>
<field-validator type="stringlength">
<param name="trim">true</param>
<param name="minLength">4</param>
<param name="maxLength">10</param>
<message key="errors.range"/>
</field-validator>
</field>
<field name="password2">
<field-validator type="requiredstring">
<message key="error.password2.required"/>
</field-validator>
</field>
<validator type="expression">
<param name="expression">password eq password2</param>
<message key="error.password.match"/>
</validator>
</validators>
@@ -0,0 +1,32 @@
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="error.username.required"/>
</field-validator>
</field>
<field name="user.fullName">
<field-validator type="requiredstring">
<message key="error.fullName.required"/>
</field-validator>
</field>
<field name="user.fromAddress">
<field-validator type="requiredstring">
<message key="error.fromAddress.required"/>
</field-validator>
<field-validator type="email">
<message key="errors.email"/>
</field-validator>
</field>
<field name="user.replyToAddress">
<field-validator type="email">
<message key="errors.email"/>
</field-validator>
</field>
</validators>
@@ -0,0 +1,101 @@
package mailreader2;
import org.apache.struts.apps.mailreader.dao.User;
/**
* <p>Insert or update a User object to the persistent store. </p>
*/
public class Registration extends MailreaderSupport {
/**
* <p>Double check that there is not a valid User login. </p>
*
* @return True if there is not a valid User login
*/
private boolean isCreating() {
User user = getUser();
return (null == user) || (null == user.getDatabase());
}
/**
* <p> Retrieve User object to edit or null if User does not exist. </p>
*
* @return The "Success" result for this mapping
* @throws Exception on any error
*/
public String input() throws Exception {
if (isCreating()) {
createInputUser();
setTask(Constants.CREATE);
} else {
setTask(Constants.EDIT);
setUsername(getUser().getUsername());
setPassword(getUser().getPassword());
setPassword2(getUser().getPassword());
}
return INPUT;
}
/**
* <p>Insert or update a Registration.</p>
*
* @return The "outcome" result code
* @throws Exception on any error
*/
public String save() throws Exception {
return execute();
}
/**
* <p> Insert or update a User object to the persistent store. </p>
* <p/>
* <p> If a User is not logged in, then a new User is created and
* automatically logged in. Otherwise, the existing User is updated. </p>
*
* @return The "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;
}
}
@@ -0,0 +1,23 @@
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="subscription.username">
<field-validator type="requiredstring">
<message key="error.username.required"/>
</field-validator>
</field>
<field name="subscription.password">
<field-validator type="requiredstring">
<message key="error.password.required"/>
</field-validator>
</field>
<field name="subscription.type">
<field-validator type="requiredstring">
<message key="error.type.invalid"/>
</field-validator>
</field>
</validators>
@@ -0,0 +1,11 @@
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="host">
<field-validator type="requiredstring">
<message key="error.host.required"/>
</field-validator>
</field>
</validators>
@@ -0,0 +1,124 @@
package mailreader2;
import com.opensymphony.xwork2.Preparable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* <p> Provide an Edit method for retrieving an existing subscription, and a
* Save method for updating or inserting a subscription. </p>
*/
public class Subscription extends MailreaderSupport
implements Preparable {
/**
* <p>Field to store list of MailServer types</p>
*/
private Map types = null;
/**
* <p>Provide the list of MailServer types.</p>
*
* @return List of MailServer types
*/
public Map getTypes() {
return types;
}
/**
* <p>Setup the MailerServer types and set the local Host property from
* the User Subscription (if any). </p>
*/
public void prepare() {
Map m = new LinkedHashMap();
m.put("imap", "IMAP Protocol");
m.put("pop3", "POP3 Protocol");
types = m;
setHost(getSubscriptionHost());
}
/**
* <p>Setup a temporary User Subscription object to capture input
* values.</p>
*
* @return INPUT
*/
public String input() {
createInputSubscription();
setTask(Constants.CREATE);
return INPUT;
}
/**
* <p>Load User Subscription for the local Host property.</p>
* <p/>
* <p>Usually, the Host is being set from the request by a link to an Edit
* or Delete task.</p>
*
* @return INPUT or Error, if Subscription is not found
*/
public String find() {
org.apache.struts.apps.mailreader.dao.Subscription
sub = findSubscription();
if (sub == null) {
return ERROR;
}
setSubscription(sub);
return INPUT;
}
/**
* <p>Prepare to present a confirmation page before removing
* Subscription.</p>
*
* @return INPUT or Error, if Subscription is not found
*/
public String delete() {
setTask(Constants.DELETE);
return find();
}
/**
* <p>Prepare to edit User Subscription.</p>
*
* @return INPUT or Error, if Subscription is not found
*/
public String edit() {
setTask(Constants.EDIT);
return find();
}
/**
* <p> Examine the Task property and DELETE, CREATE, or save the User
* Subscription, as appropriate. </p>
*
* @return SUCCESS
* @throws Exception on a database error
*/
public String save() throws Exception {
if (Constants.DELETE.equals(getTask())) {
removeSubscription();
}
if (Constants.CREATE.equals(getTask())) {
copySubscription(getHost());
}
if (hasErrors()) return INPUT;
saveUser();
return SUCCESS;
}
}
@@ -0,0 +1,28 @@
package mailreader2;
/**
* Verify that essential resources are available.
*/
public class Welcome extends MailreaderSupport {
public String execute() {
// Confirm message resources loaded
String message = getText(Constants.ERROR_DATABASE_MISSING);
if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
}
// Confirm database loaded
if (null==getDatabase()) {
addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
}
if (hasErrors()) {
return ERROR;
}
else {
return SUCCESS;
}
}
}
@@ -0,0 +1,4 @@
struts.objectFactory = spring
struts.devMode = false
struts.action.extension = do
struts.enable.DynamicMethodInvocation = false
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-default.xml"/>
<include file="mailreader-default.xml"/>
<include file="mailreader-support.xml"/>
</struts>
@@ -0,0 +1,3 @@
password=Enter your Password here ==>
struts.logo.path=struts-power.gif
struts.logo.alt=Powered by Struts
@@ -0,0 +1 @@
.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==>
@@ -0,0 +1,13 @@
<?xml version='1.0'?>
<database>
<user username="user" fromAddress="John.User@somewhere.com"
fullName="John Q. User" password="pass">
<subscription host="mail.hotmail.com" autoConnect="false"
password="bar" type="pop3" username="user1234">
</subscription>
<subscription host="mail.yahoo.com" autoConnect="false" password="foo"
type="imap" username="jquser">
</subscription>
</user>
</database>
@@ -0,0 +1,25 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><s:text name="change.title"/></title>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body>
<p>
<s:text name="change.message"/>
</p>
<p>
<a href="<s:url action="Login!input"/>">
<s:text name="change.try"/>
</a>
</p>
</body>
</html>
@@ -0,0 +1,40 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Unexpected Error</title>
</head>
<body>
<h2>An unexpected error has occured</h2>
<p>
Please report this error to your system administrator
or appropriate technical support personnel.
Thank you for your cooperation.
</p>
<hr/>
<h3>Error Message</h3>
<s:actionerror />
<p>
<s:property value="%{exception.message}"/>
</p>
<hr/>
<h3>Technical Details</h3>
<p>
<s:property value="%{exceptionStack}"/>
</p>
<jsp:include page="Footer.jsp"/>
</body>
</html>
@@ -0,0 +1,6 @@
<%@ taglib uri="/struts-tags" prefix="s" %>
<hr/>
<p>
<a href="<s:url action="Welcome" />"><s:text name="index.title"/></a>
</p>
@@ -0,0 +1,30 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><s:text name="login.title"/></title>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body onLoad="self.focus();document.Login.username.focus()">
<s:actionerror />
<s:form action="Login" validate="true">
<s:textfield label="%{getText('username')}" name="username"/>
<s:password label="%{getText('password')}" name="password" showPassword="true"/>
<s:submit value="%{getText('button.save')}"/>
<s:reset value="%{getText('button.reset')}"/>
<s:submit action="Login!cancel" value="%{getText('button.cancel')}"
onclick="form.onsubmit=null"/>
</s:form>
<jsp:include page="Footer.jsp"/>
</body>
</html>
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/">
</Context>
@@ -0,0 +1,25 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><s:text name="mainMenu.title"/></title>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body>
<h3><s:text name="mainMenu.heading"/> <s:property
value="user.fullName"/></h3>
<ul>
<li><a href="<s:url action="Registration!input" />">
<s:text name="mainMenu.registration"/>
</a>
</li>
<li><a href="<s:url action="Logout"/>">
<s:text name="mainMenu.logout"/>
</a>
</ul>
</body>
</html>
@@ -0,0 +1,126 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<s:if test="task=='Create'">
<title><s:text name="registration.title.create"/></title>
</s:if>
<s:if test="task=='Edit'">
<title><s:text name="registration.title.edit"/></title>
</s:if>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body onLoad="self.focus();document.Registration.username.focus()">
<s:actionerror/>
<s:form action="Registration!save" validate="false">
<s:token />
<s:hidden name="task"/>
<s:if test="task == 'Create'">
<s:textfield label="%{getText('username')}" name="username"/>
</s:if>
<s:else>
<s:label label="%{getText('username')}" name="username"/>
<s:hidden name="username"/>
</s:else>
<s:password label="%{getText('password')}" name="password"/>
<s:password label="%{getText('password2')}" name="password2"/>
<s:textfield label="%{getText('fullName')}"
name="user.fullName"/>
<s:textfield label="%{getText('fromAddress')}"
name="user.fromAddress"/>
<s:textfield label="%{getText('replyToAddress')}"
name="user.replyToAddress"/>
<s:if test="task == 'Create'">
<s:submit value="%{getText('button.save')}" action="Registration!save"/>
<s:reset value="%{getText('button.reset')}"/>
<s:submit action="Welcome" value="%{getText('button.cancel')}"
onclick="form.onsubmit=null"/>
</s:if>
<s:else>
<s:submit value="%{getText('button.save')}" action="Registration"/>
<s:reset value="%{getText('button.reset')}"/>
<s:submit action="MainMenu" value="%{getText('button.cancel')}"
onclick="form.onsubmit=null"/>
</s:else>
</s:form>
<s:if test="task == 'Edit'">
<div align="center">
<h3><s:text name="heading.subscriptions"/></h3>
</div>
<table border="1" width="100%">
<tr>
<th align="center" width="30%">
<s:text name="heading.host"/>
</th>
<th align="center" width="25%">
<s:text name="heading.user"/>
</th>
<th align="center" width="10%">
<s:text name="heading.type"/>
</th>
<th align="center" width="10%">
<s:text name="heading.autoConnect"/>
</th>
<th align="center" width="15%">
<s:text name="heading.action"/>
</th>
</tr>
<s:iterator value="user.subscriptions">
<tr>
<td align="left">
<s:property value="host"/>
</td>
<td align="left">
<s:property value="username"/>
</td>
<td align="center">
<s:property value="type"/>
</td>
<td align="center">
<s:property value="autoConnect"/>
</td>
<td align="center">
<a href="<s:url action="Subscription!delete"><s:param name="host" value="host"/></s:url>">
<s:text name="registration.deleteSubscription"/>
</a>
&nbsp;
<a href="<s:url action="Subscription!edit"><s:param name="host" value="host"/></s:url>">
<s:text name="registration.editSubscription"/>
</a>
</td>
</tr>
</s:iterator>
</table>
<a href="<s:url action="Subscription!input"/>"><s:text
name="registration.addSubscription"/></a>
</s:if>
<jsp:include page="Footer.jsp"/>
</body>
</html>
@@ -0,0 +1,68 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<s:if test="task=='Create'">
<title><s:text name="subscription.title.create"/></title>
</s:if>
<s:if test="task=='Edit'">
<title><s:text name="subscription.title.edit"/></title>
</s:if>
<s:if test="task=='Delete'">
<title><s:text name="subscription.title.delete"/></title>
</s:if>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body onLoad="self.focus();document.Subscription.username.focus()">
<s:actionerror/>
<s:form action="Subscription!save" validate="true">
<s:token />
<s:hidden name="task"/>
<s:label label="%{getText('username')}" name="user.username"/>
<s:if test="task == 'Create'">
<s:textfield label="%{getText('mailHostname')}" name="host"/>
</s:if>
<s:else>
<s:label label="%{getText('mailHostname')}" name="host"/>
<s:hidden name="host"/>
</s:else>
<s:if test="task == 'Delete'">
<s:label label="%{getText('mailUsername')}"
name="subscription.username"/>
<s:label label="%{getText('mailPassword')}"
name="subscription.password"/>
<s:label label="%{getText('mailServerType')}"
name="subscription.type"/>
<s:label label="%{getText('autoConnect')}"
name="subscription.autoConnect"/>
<s:submit value="%{getText('button.confirm')}"/>
</s:if>
<s:else>
<s:textfield label="%{getText('mailUsername')}"
name="subscription.username"/>
<s:textfield label="%{getText('mailPassword')}"
name="subscription.password"/>
<s:select label="%{getText('mailServerType')}"
name="subscription.type" list="types"/>
<s:checkbox label="%{getText('autoConnect')}"
name="subscription.autoConnect"/>
<s:submit value="%{getText('button.save')}"/>
<s:reset value="%{getText('button.reset')}"/>
</s:else>
<s:submit action="Registration!input"
value="%{getText('button.cancel')}"
onclick="form.onsubmit=null"/>
</s:form>
<jsp:include page="Footer.jsp"/>
</body>
</html>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Struts 2 Mailreader</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext*.xml</param-value>
</context-param>
<filter>
<filter-name>Struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>Struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Application Listener for Mailreader database -->
<listener>
<listener-class>
mailreader2.ApplicationListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
@@ -0,0 +1,56 @@
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><s:text name="index.title"/></title>
<link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
type="text/css"/>
</head>
<body>
<h3><s:text name="index.heading"/></h3>
<ul>
<li><a href="<s:url action="Registration!input"/>"><s:text
name="index.registration"/></a></li>
<li><a href="<s:url action="Login!input"/>"><s:text
name="index.login"/></a></li>
</ul>
<h3>Language Options</h3>
<ul>
<li>
<s:url id="en" action="Welcome">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{en}">English</s:a>
</li>
<li>
<s:url id="ja" action="Welcome">
<s:param name="request_locale">ja</s:param>
</s:url>
<s:a href="%{ja}">Japanese</s:a>
</li>
<li>
<s:url id="ru" action="Welcome">
<s:param name="request_locale">ru</s:param>
</s:url>
<s:a href="%{ru}">Russian</s:a>
</li>
</ul>
<hr/>
<p><s:i18n name="alternate">
<img src="<s:text name="struts.logo.path"/>"
alt="<s:text name="struts.logo.alt"/>"/>
</s:i18n></p>
<p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
</body>
</html>
@@ -0,0 +1,46 @@
/**
* Mailreader stylesheet
*/
body {
background-color: #FFFFFF;
color: #000000;
link: 000066;
visited: #660066;
active: #33CCCC;
}
A:hover {
color: #FF0000;
}
h1 {
font-family: Arial, Helvetica, sans-serif;
}
h2 {
font-family: Arial, Helvetica, sans-serif;
}
h3 {
font-family: Arial, Helvetica, sans-serif;
}
h4 {
font-family: Arial, Helvetica, sans-serif;
}
h5 {
font-family: Arial, Helvetica, sans-serif;
}
h6 {
font-family: Arial, Helvetica, sans-serif;
}
font.hint {
font-style: italic;
font-size: 80%;
font-family: Arial, Helvetica, sans-serif;
text-align: left;
}
@@ -0,0 +1,10 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.do">
</head>
<body>
<p>Loading ...</p>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because it is too large Load Diff
+196
View File
@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
<name>Webapps</name>
<modules>
<module>blank</module>
<module>mailreader</module>
<module>portlet</module>
<module>showcase</module>
</modules>
<distributionManagement>
<site>
<id>apache-site</id>
<url>scp://people.apache.org/www/struts.apache.org/struts2/apps</url>
</site>
</distributionManagement>
<profiles>
<profile>
<id>hostedqa</id>
<dependencies>
<dependency>
<groupId>com.hostedqa</groupId>
<artifactId>hostedqa-remote-ant</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>codehaus</id>
<name>codehaus</name>
<url>http://repository.codehaus.org</url>
</repository>
<repository>
<id>maven-hostedqa</id>
<name>maven-hostedqa</name>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
<url>http://maven.hostedqa.com</url>
</repository>
</repositories>
<build>
<resources>
<!-- Include resources under src/main/java in WEB-INF/classes -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<taskdef resource="hostedqatasks" classpathref="maven.plugin.classpath"/>
<upload file="${project.build.directory}/${project.build.finalName}.war"
account="struts" email="${email}"
password="${password}" resourceId="${resourceId}"/>
<playsuite suiteId="${suiteId}" clientConfigs="${clientConfigs}" appConfigs="${appConfigs}" account="struts"
email="${email}"
password="${password}"/>
</tasks>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.hostedqa</groupId>
<artifactId>hostedqa-remote-ant</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat5x</containerId>
<home>${cargo.tomcat5x.home}</home>
<log>${project.build.directory}/tomcat5x.log</log>
<output>${project.build.directory}/tomcat5x.out</output>
</container>
<configuration>
<home>${project.build.directory}/tomcat5x</home>
</configuration>
</configuration>
</plugin>
<!-- Include source code under WEB-INF/src/java -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>copy-sources</id>
<phase>process-sources</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/${pom.artifactId}/WEB-INF/src/java"
failonerror="false">
<fileset dir="${basedir}/src/main/java"/>
</copy>
<copy todir="${project.build.directory}/${pom.artifactId}/WEB-INF/src/java"
failonerror="false">
<fileset dir="${basedir}/src/main/resources"/>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<finalName>${pom.artifactId}</finalName>
</build>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${pom.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>1.2.8</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
+17
View File
@@ -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/<your_portal_server>/ into the
WAR's WEB-INF directory.
----------------------------------------------------------------------------
+36
View File
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-portlet</artifactId>
<packaging>war</packaging>
<name>Portlet Webapp</name>
<dependencies>
<dependency>
<groupId>portlet-api</groupId>
<artifactId>portlet-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>struts-portlet</display-name>
<!-- Uncomment/comment this if you need/don't need Spring support -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<filter>
<filter-name>action2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.apache.struts2.portlet.context.ServletContextHolderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.exoplatform.services.portletcontainer.impl.servlet.PortletApplicationListener
</listener-class>
</listener>
<servlet>
<servlet-name>preparator</servlet-name>
<servlet-class>
org.apache.struts2.portlet.context.PreparatorServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>PortletWrapper</servlet-name>
<servlet-class>
org.exoplatform.services.portletcontainer.impl.servlet.ServletWrapper
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PortletWrapper</servlet-name>
<url-pattern>/PortletWrapper</url-pattern>
</servlet-mapping>
</web-app>
@@ -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.
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app-collection>
<portlet-app-def>
<portlet-app id="org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet">
<portlet-name>JSR Portlet Servlet</portlet-name>
<servlet-name>PortletServlet</servlet-name>
</portlet-app>
<concrete-portlet-app id="org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet.1">
<concrete-portlet>
<portlet-name>Portlet Servlet</portlet-name>
<default-locale>en</default-locale>
<language locale="en">
<title>Portlet Servlet</title>
<title-short>Portlet Servlet</title-short>
<description>A JSR Portlet Loader</description>
<keywords>portlet servlet</keywords>
</language>
</concrete-portlet>
</concrete-portlet-app>
</portlet-app-def>
</portlet-app-collection>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<portlet-group>
<group-name>StrutsPortlet</group-name>
<group-description>StrutsPortlet Example Application</group-description>
<group-visibility>PUBLIC</group-visibility>
<portlet-role-info>
<portlet-class>struts-portlet#StrutsPortlet</portlet-class>
<required-role>USER</required-role>
</portlet-role-info>
</portlet-group>
@@ -0,0 +1,19 @@
<portlet-tabbed-pane>
<portlet-tab label="StrutsPortlet">
<title lang="en">StrutsPortlet Example</title>
<portlet-tabbed-pane style="sub-menu">
<portlet-tab label="strutsportlettab">
<title lang="en">StrutsPortlet Example Application</title>
<table-layout>
<row-layout>
<column-layout>
<portlet-frame label="strutsportlet">
<portlet-class>struts-portlet#StrutsPortlet</portlet-class>
</portlet-frame>
</column-layout>
</row-layout>
</table-layout>
</portlet-tab>
</portlet-tabbed-pane>
</portlet-tab>
</portlet-tabbed-pane>
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>struts-portlet</display-name>
<!-- Uncomment/comment this if you need/don't need Spring support -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<filter>
<filter-name>action2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>action2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.apache.struts2.portlet.context.ServletContextHolderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet
</listener-class>
</listener>
<servlet>
<servlet-name>preparator</servlet-name>
<servlet-class>
org.apache.struts2.portlet.context.PreparatorServlet
</servlet-class>
</servlet>
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>PortletServlet</servlet-name>
<servlet-class>
org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PortletServlet</servlet-name>
<url-pattern>/jsr/struts-portlet</url-pattern>
</servlet-mapping>
</web-app>
@@ -0,0 +1,3 @@
<jboss-app>
<app-name>struts-portlet</app-name>
</jboss-app>
@@ -0,0 +1,12 @@
<portlet-app>
<portlet>
<portlet-name>StrutsPortlet</portlet-name>
<security>
</security>
</portlet>
<portlet>
<portlet-name>StrutsPortlet2</portlet-name>
<security>
</security>
</portlet>
</portlet-app>
@@ -0,0 +1,3 @@
<?xml version="1.0"?>
<jboss-web>
</jboss-web>
@@ -0,0 +1,11 @@
<?xml version="1.0" standalone="yes"?>
<instances>
<instance>
<instance-name>StrutsPortletInstance</instance-name>
<component-ref>StrutsPortlet</component-ref>
</instance>
<instance>
<instance-name>StrutsPortlet2Instance</instance-name>
<component-ref>StrutsPortlet2</component-ref>
</instance>
</instances>
@@ -0,0 +1,18 @@
<pages>
<portal-name>default</portal-name>
<page>
<page-name>struts-portlet</page-name>
<window>
<window-name>StrutsPortletWindow</window-name>
<instance-ref>struts-portlet.StrutsPortlet.StrutsPortletInstance</instance-ref>
<region>left</region>
<height>0</height>
</window>
<window>
<window-name>StrutsPortletWindow2</window-name>
<instance-ref>struts-portlet.StrutsPortlet2.StrutsPortlet2Instance</instance-ref>
<region>right</region>
<height>0</height>
</window>
</page>
</pages>
@@ -0,0 +1,3 @@
<jboss-app>
<app-name>struts-portlet</app-name>
</jboss-app>
@@ -0,0 +1,12 @@
<portlet-app>
<portlet>
<portlet-name>StrutsPortlet</portlet-name>
<security>
</security>
</portlet>
<portlet>
<portlet-name>StrutsPortlet2</portlet-name>
<security>
</security>
</portlet>
</portlet-app>

Some files were not shown because too many files have changed in this diff Show More