Initial commit

parents
Showing with 4043 additions and 0 deletions
9780596003289
\ No newline at end of file
## Example files for the title:
# Programming Jakarta Struts, by Chuck Cavaness
[![Programming Jakarta Struts, by Chuck Cavaness](http://akamaicovers.oreilly.com/images/9780596003289/cat.gif)](https://www.safaribooksonline.com/library/view/title/0596003285//)
The following applies to example files from material published by O’Reilly Media, Inc. Content from other publishers may include different rules of usage. Please refer to any additional usage rights explained in the actual example files or refer to the publisher’s website.
O'Reilly books are here to help you get your job done. In general, you may use the code in O'Reilly books in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from our books does not require permission. Answering a question by citing our books and quoting example code does not require permission. On the other hand, selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Incorporating a significant amount of example code from our books into your product's documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN.
If you think your use of code examples falls outside fair use or the permission given here, feel free to contact us at <permissions@oreilly.com>.
Please note that the examples are not production code and have not been carefully testing. They are provided "as-is" and come with no warranty of any kind.
No preview for this file type
<project name="banking" default="war" basedir=".">
<!-- change these to suit environment -->
<property name="jdk.home" value="c:/jdk1.3"/>
<!-- resin setup -->
<!-- <property name="webserver.home" value="/usr/local/java/resin"/>
<property name="webserver.deploy" value="${webserver.home}/webapps"/>
<property name="servlet.jar" value="${webserver.home}/lib/jsdk23.jar"/>
-->
<!-- tomcat 3.3 setup -->
<!-- <property name="webserver.home" value="/usr/local/java/jakarta-tomcat-3.3a"/>
<property name="webserver.deploy" value="${webserver.home}/webapps"/>
<property name="servlet.jar" value="${webserver.home}/lib/common/servlet.jar"/>
-->
<!-- catalina (tomcat 4) setup -->
<property name="webserver.home" value="c:/tomcat"/>
<property name="webserver.deploy" value="${webserver.home}/webapps"/>
<property name="servlet.jar" value="${webserver.home}/common/lib/servlet.jar"/>
<!-- weblogic 6.1 setup -->
<!-- <property name="webserver.home" value="/usr/local/java/bea/wlserver6.1"/>
<property name="webserver.deploy" value="${webserver.home}/config/mydomain/applications"/>
<property name="servlet.jar" value="${webserver.home}/lib/j2ee12.jar"/>
-->
<!-- jboss 2.4.4/catalina (tomcat 4) setup -->
<!-- <property name="webserver.home" value="/usr/local/jboss/jboss"/>
<property name="webserver.deploy" value="${webserver.home}/deploy"/>
<property name="servlet.jar" value="${webserver.home}/../catalina/common/lib/servlet.jar"/>
-->
<!-- project structure - should not have to modify -->
<property name="src.dir" value="src"/>
<property name="web.dir" value="web"/>
<property name="build.dir" value="build"/>
<property name="dist.dir" value="dist"/>
<property name="lib.dir" value="lib"/>
<!-- CLASSPATH used during compilation -->
<path id="build.classpath">
<pathelement location="${servlet.jar}"/>
<pathelement location="${lib.dir}/commons-beanutils.jar"/>
<pathelement location="${lib.dir}/commons-collections.jar"/>
<pathelement location="${lib.dir}/commons-dbcp.jar"/>
<pathelement location="${lib.dir}/commons-digester.jar"/>
<pathelement location="${lib.dir}/commons-logging.jar"/>
<pathelement location="${lib.dir}/commons-pool.jar"/>
<pathelement location="${lib.dir}/commons-services.jar"/>
<pathelement location="${lib.dir}/commons-validator.jar"/>
<pathelement location="${lib.dir}/jdbc2_0-stdext.jar"/>
<pathelement location="${lib.dir}/log4j.jar"/>
<pathelement location="${lib.dir}/poolman.jar"/>
<pathelement location="${lib.dir}/struts.jar"/>
<pathelement location="${lib.dir}/tiles.jar"/>
<pathelement path="${build.dir}" />
</path>
<!--
Pre-compilation rule
-->
<target name="prepare">
<tstamp/>
<mkdir dir="${build.dir}" />
<mkdir dir="${dist.dir}/lib" />
</target>
<!--
Compiling rule
-->
<target name="compile" depends="prepare">
<javac destdir="${build.dir}" deprecation="on">
<classpath refid="build.classpath" />
<src path="${src.dir}" />
</javac>
</target>
<!--
WAR rules
-->
<target name="war" depends="compile">
<echo>building war...</echo>
<war warfile="${dist.dir}/lib/banking.war" webxml="${web.dir}/WEB-INF/web.xml">
<fileset dir="${web.dir}"/>
<classes dir="${build.dir}"/>
<classes dir="${lib.dir}">
<include name="*.properties"/>
</classes>
<lib dir="${lib.dir}">
<include name="*.jar"/>
</lib>
</war>
</target>
<!--
Deploy rule
-->
<target name="deploy" depends="war">
<echo>copying war file to deployment dir...</echo>
<copy file="${dist.dir}/lib/banking.war" todir="${webserver.deploy}"/>
</target>
<!--
clean compilation remnants
-->
<target name="clean">
<delete dir="${build.dir}" />
</target>
<!--
completely clean all compilation results
-->
<target name="distclean">
<antcall target="clean"/>
<delete dir="${dist.dir}" />
</target>
</project>
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
No preview for this file type
package com.oreilly.struts.banking;
public interface IConstants {
public static final String USER_VIEW_KEY="USER_VIEW";
public static final String SUCCESS_KEY = "Success";
public static final String SYSTEM_FAILURE_KEY = "SystemFailure";
public static final String SESSION_TIME_OUT_KEY = "SessionTimeOut";
public static final String FAILURE_KEY = "Failure";
public static final String USER_CONTAINER_KEY = "UserContainer";
public static final String APPLICATION_CONTAINER_KEY = "ApplicationContainer";
public static final String SIGNON_KEY = "Login";
public static final String LOGIN_TOKEN_KEY = "LoginTokenKey";
public static final String IMAGE_RESOURCE_KEY = "IMAGE_RESOURCE_KEY";
}
\ No newline at end of file
package com.oreilly.struts.banking.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.*;
import com.oreilly.struts.banking.IConstants;
import com.oreilly.struts.banking.view.AccountDetailView;
import com.oreilly.struts.banking.service.AccountService;
import com.oreilly.struts.banking.util.BankingUtil;
/**
* Struts action that gets the AccountDetailView object based on
* an id. The id must be passed in a request parameter with the name id.
*/
public class GetAccountDetailAction extends Action {
public ActionForward execute( ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// Check for a timeout
if ( !BankingUtil.isLoggedIn(request) ){
return mapping.findForward( "SessionTimeOut" );
}
// Get the id for the account from the request parameters
String acctId = request.getParameter( "id" );
// Create an instance of the account service and call it
AccountService service = new AccountService();
AccountDetailView detailView = service.getAccountDetailView( acctId );
// Insert the returned view back into the form and return
((DynaActionForm)form).set( "view", detailView );
return mapping.findForward( IConstants.SUCCESS_KEY );
}
}
package com.oreilly.struts.banking.action;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.*;
import com.oreilly.struts.banking.service.AccountService;
import com.oreilly.struts.banking.IConstants;
import com.oreilly.struts.banking.view.UserView;
import com.oreilly.struts.banking.util.BankingUtil;
/**
* Struts action that gets a List of AccountSummaryView objects for the user
* based on the user's id. The id is stored in a UserView inside the session.
*/
public class GetAccountInformationAction extends Action {
public ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
if ( !BankingUtil.isLoggedIn(request) ){
return mapping.findForward( "SessionTimeOut" );
}
// Get the UserView from the session
UserView userView =
(UserView)request.getSession().getAttribute( IConstants.USER_VIEW_KEY );
// Create an instance of the account service and call it
AccountService service = new AccountService();
List accounts = service.getAccountSummaries( userView.getId() );
// Put the accounts into the form and return
((DynaActionForm)form).set( "accounts", accounts );
return mapping.findForward( IConstants.SUCCESS_KEY );
}
}
package com.oreilly.struts.banking.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import com.oreilly.struts.banking.IConstants;
import com.oreilly.struts.banking.service.IAuthentication;
import com.oreilly.struts.banking.service.SecurityService;
import com.oreilly.struts.banking.service.InvalidLoginException;
import com.oreilly.struts.banking.view.UserView;
import com.oreilly.struts.banking.form.LoginForm;
/**
* This Action is called by the ActionServlet when a login attempt
* is made by the user. The ActionForm should be an instance of
* a LoginForm and contain the credentials needed by the SecurityService.
*/
public class LoginAction extends Action {
public ActionForward execute( ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// The ActionForward to return when completed
ActionForward forward = null;
UserView userView = null;
// Get the credentials from the LoginForm
String accessNbr = ((LoginForm)form).getAccessNumber();
String pinNbr = ((LoginForm)form).getPinNumber();
/*
* In a real application, you would typically get a reference
* to a security service through something like JNDI or a factory.
*/
IAuthentication service = new SecurityService();
// Attempt to login
userView = service.login(accessNbr, pinNbr);
// Since an exception wasn't thrown, login was successful
// Invalidate existing session if it exists
HttpSession session = request.getSession(false);
if(session != null) {
session.invalidate();
}
// Create a new session for this user
session = request.getSession(true);
// Store the UserView into the session and return
session.setAttribute( IConstants.USER_VIEW_KEY, userView );
forward = mapping.findForward(IConstants.SUCCESS_KEY );
return forward;
}
}
package com.oreilly.struts.banking.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts.action.*;
/**
* This Struts action logs the user out of the system and invalidates the
* session.
*/
public class LogoutAction extends Action {
public ActionForward execute( ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// Invalidate the User's session if one exists
HttpSession session = request.getSession(false);
if(session != null) {
session.invalidate();
}
return mapping.findForward("Success");
}
}
package com.oreilly.struts.banking.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;
/**
* This ActionForm is used by the online banking appliation to validate
* that the user has entered an accessNumber and a pinNumber. If one or
* both of the fields are empty when validate is called by the
* ActionServlet, error messages are created.
*/
public class LoginForm extends ActionForm {
// The user's private id number
private String pinNumber;
// The user's access number
private String accessNumber;
public LoginForm() {
super();
resetFields();
}
/**
* Called by the framework to validate the user has entered the
* accessNumber and pin fields.
*/
public ActionErrors validate(ActionMapping mapping, HttpServletRequest req ){
ActionErrors errors = new ActionErrors();
// Get access to the message resources for this application
// There's not an easy way to access the resources from an ActionForm
MessageResources resources =
(MessageResources)req.getAttribute( Action.MESSAGES_KEY );
// Check and see if the access number is missing
if(accessNumber == null || accessNumber.length() == 0) {
String accessNumberLabel = resources.getMessage( "label.accessnumber" );
ActionError newError =
new ActionError("global.error.login.requiredfield", accessNumberLabel );
errors.add(ActionErrors.GLOBAL_ERROR, newError);
}
// Check and see if the pin number is missing
if(pinNumber == null || pinNumber.length() == 0) {
String pinNumberLabel = resources.getMessage( "label.pinnumber" );
ActionError newError =
new ActionError("global.error.login.requiredfield", pinNumberLabel );
errors.add(ActionErrors.GLOBAL_ERROR, newError);
}
// Return the ActionErrors, in any.
return errors;
}
/**
* Called by the framework to reset the fields back to their default values.
*/
public void reset(ActionMapping mapping, HttpServletRequest request) {
// Clear out the access number and pin number fields
resetFields();
}
/**
* Reset the fields back to their defaults.
*/
protected void resetFields() {
this.accessNumber = "";
this.pinNumber = "";
}
public void setAccessNumber(String nbr) {
this.accessNumber = nbr;
}
public String getAccessNumber() {
return this.accessNumber;
}
public String getPinNumber() {
return this.pinNumber;
}
public void setPinNumber(String nbr) {
this.pinNumber = nbr;
}
}
package com.oreilly.struts.banking.service;
import java.util.*;
import com.oreilly.struts.banking.view.AccountSummaryView;
import com.oreilly.struts.banking.view.AccountDetailView;
/**
* Used by the example banking application to simulate a datastore.
*/
public class AccountService {
// A map to hold the users accounts
private static Map accountMap = new HashMap();
/**
* Default Constructor
*/
public AccountService() {
super();
}
/**
* Retrieve an AccountDetailView belonging to the user with the acctId.
*/
public AccountDetailView getAccountDetailView( String acctId ) {
return (AccountDetailView)accountMap.get( acctId );
}
/**
* Retrieve a collection of AccountSummaryView objects for the user.
*/
public List getAccountSummaries(String userId) {
return new ArrayList( accountMap.values() );
}
// This data is just dummied up for the example. In a real application,
// all of this would come from the database.
static{
Calendar cal = java.util.GregorianCalendar.getInstance();
AccountDetailView view1 = new AccountDetailView();
view1.setAccountId("1211-098");
view1.setAccountType("CHECKING");
view1.setAccountBalance(new Double(372.63));
view1.setAccountName("PERFORMANCE");
view1.setWithdrawls( new Double(100.00) );
view1.setDeposits( new Double(472.63) );
cal.set( 1999, 1, 23 );
view1.setOpeningDate( cal.getTime() );
accountMap.put( view1.getAccountId(), view1 );
AccountDetailView view2 = new AccountDetailView();
view2.setAccountId("389-341");
view2.setAccountType("SAVINGS");
view2.setAccountBalance(new Double(1372.63));
view2.setAccountName("REGULAR");
view2.setWithdrawls( new Double(20.00) );
view2.setDeposits( new Double(1392.63) );
cal.set( 2000, 5, 3 );
view2.setOpeningDate( cal.getTime() );
accountMap.put( view2.getAccountId(), view2 );
}
}
package com.oreilly.struts.banking.service;
import com.oreilly.struts.banking.view.UserView;
/**
* Provides methods that the banking security service should implement.
*/
public interface IAuthentication {
/**
* The login method is called when a user wishes to login to
* the online banking application.
* @param accessNumber The account access number.
* @param pin The account private id number.
* @returns A DTO object representing the user's personal data.
* @throws InvalidLoginException if the credentials are invalid.
*/
public UserView login( String accessNumber, String pin )
throws InvalidLoginException;
}
package com.oreilly.struts.banking.service;
/**
* Thrown when a user attempts to login with invalid credentials.
*/
public class InvalidLoginException extends Exception {
public InvalidLoginException( String msg ){
super( msg );
}
}
package com.oreilly.struts.banking.service;
import com.oreilly.struts.banking.view.UserView;
/**
* Used by the example banking application to simulate a security service.
*/
public class SecurityService implements IAuthentication {
public UserView login(String accessNumber, String pin )
throws InvalidLoginException {
// A real security service would check the login against a security realm
// This example is hard coded to only let in 123/456
if( "123".equals( accessNumber) && "456".equals(pin) ){
/* Dummy a UserView for this example.
* This data/object would typically come from the business layer
* after proper authentication/authorization had been done.
*/
UserView userView = new UserView( "John", "Doe" );
userView.setId( "39017" );
return userView;
}
else {
// If the login method is invalid, throw an InvalidLoginException
// Create a msg that can be inserted into a log file
String msg = "Invalid Login Attempt by " + accessNumber + ":" + pin;
throw new InvalidLoginException( msg );
}
}
}
package com.oreilly.struts.banking.util;
import javax.servlet.http.HttpServletRequest;
import com.oreilly.struts.banking.IConstants;
public class BankingUtil {
/**
* Return true if there's a UserView object stored in the session, false otherwise.
*/
public static boolean isLoggedIn( HttpServletRequest request ){
if ( request.getSession(false) == null ||
(request.getSession().getAttribute( IConstants.USER_VIEW_KEY ) == null)){
return false;
} else{
return true;
}
}
}
\ No newline at end of file
package com.oreilly.struts.banking.view;
import java.util.Date;
/**
* A value object that holds detailed information for a user account.
*/
public class AccountDetailView extends AccountSummaryView {
private Double withdrawls;
private Date openingDate;
private Double deposits;
/**
* Default Constructor
*/
public AccountDetailView() {
super();
}
public Double getWithdrawls() {
return withdrawls;
}
public void setWithdrawls(Double newWithdrawls) {
withdrawls = newWithdrawls;
}
public void setDeposits(Double newDeposits) {
deposits = newDeposits;
}
public Double getDeposits() {
return deposits;
}
public Date getOpeningDate(){
return openingDate;
}
public void setOpeningDate( Date aDate ){
openingDate = aDate;
}
}
package com.oreilly.struts.banking.view;
/**
* A value object that holds summary information for a user account.
*/
public class AccountSummaryView implements java.io.Serializable {
private String accountId;
private Double accountBalance;
private String accountName;
private String accountType;
/**
* Default Constructor
*/
public AccountSummaryView() {
super();
}
public String getAccountType() {
return accountType;
}
public void setAccountBalance(Double newAccountBalance) {
accountBalance = newAccountBalance;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String newAccountId) {
accountId = newAccountId;
}
public Double getAccountBalance() {
return accountBalance;
}
public String getAccountName() {
return accountName;
}
public void setAccountType(String newAccountType) {
accountType = newAccountType;
}
public void setAccountName(String newAccountName) {
accountName = newAccountName;
}
}
package com.oreilly.struts.banking.view;
import java.util.Set;
import java.util.HashSet;
/**
* A value object for that wraps all of the user's security information
*/
public class UserView implements java.io.Serializable {
private String id;
private String lastName;
private String firstName;
// A unique collection of permission String objects
private Set permissions = null;
public UserView(String first, String last) {
this(first, last, new HashSet());
}
public UserView(String first, String last, Set userPermissions) {
super();
firstName = first;
lastName = last;
permissions = userPermissions;
}
public boolean containsPermission(String permissionName) {
return permissions.contains(permissionName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String name) {
lastName = name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String name) {
firstName = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
\ No newline at end of file
# Labels
label.accessnumber=Access Number
label.pinnumber=Pin Number
label.accounts=Accounts
label.balance=Balance
label.totalassets=Total Assets
label.account=Account
label.balance=Available Balance
label.description=Description
label.amount=Amount
label.deposits=Deposits
label.withdrawls=Withdrawls
label.openingbalance=Opening Balance
# Links
link.customeragreement=Customer Agreement
link.privacy=Privacy
link.security=Security
link.viewaccountdetail=View Account Detail
# Page Titles
title.login=Struts Online Banking - Account Login
title.accountinfo=Struts Online Banking - Account Information
title.accountdetail=Struts Online Banking - Account Detail
# Button Labels
label.button.login=Login
# Error messages
global.error.invalidlogin=<li>Invalid Access Number and/or Pin</li>
global.error.login.requiredfield=<li>The {0} is required for login</li>
# Images
image.logo=images/logo.gif
image.logo.alt=Struts Online Banking
image.logout=images/logout.gif
image.logout.alt=Logout
image.strutspower=images/struts-power.gif
image.strutspower.alt=Powered By Struts
image.transfer=images/transfer.gif
image.transfer.alt="Transfer Funds"
image.clear=images/clear.gif
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog