Java tutorial
package com.m2a.struts; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.HashMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.commons.scaffold.lang.BaseException; import org.apache.commons.scaffold.lang.Tokens; import org.apache.commons.scaffold.util.ProcessBean; import org.apache.commons.scaffold.util.ProcessResult; import org.apache.log4j.Category; import org.apache.struts.scaffold.BaseHelperAction; import com.m2a.struts.M2AFormBase; import com.m2a.util.M2ACookies; import com.m2a.resources.M2ATokens; /** * Description : Advanced framework class to instantiate and execute helper beans and process the result * Author : Guna V Ciju Sarath M Dinesh J Senthivel U S * Date Written : Jan 16 2003 * Called By : M2AProcessBridgeAction * Calling : * Modified On : 20111212:1 * Modified By : Srinivasan T * Modification : FORM_LIST scope added in exposeInScope * * Modified On : 20120528:1 * Modified By : Srinivasan T * Modification : Catch Exception additional line of codes commented. * Known Bugs */ public class M2AProcessBridgeAction extends BaseHelperAction { // Log4j for logging private Category log = Category.getInstance(M2AProcessBridgeAction.class.getName()); // --------------------------------------------------------- Public Methods /** * Exposes result in a servlet context. * * @param mapping the request being serviced * @param request the request being serviced * @param request the request being serviced * @param name The name to use in scope * @param scope The scope to set the attribute in * @param bean The attribute to be set */ protected void exposeInScope(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String name, String scope, Object bean) { if (log.isDebugEnabled()) { log.debug("*** Executing exposeInScope()"); } if (null == scope) { if (log.isDebugEnabled()) { log.debug("*** Scope is NULL"); } } else { if (log.isDebugEnabled()) { log.debug("*** Scope is " + scope); } } if (null == bean) { if (log.isDebugEnabled()) { log.debug("*** Result bean is NULL"); } } else if (Tokens.REQUEST.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean in Request scope"); } request.setAttribute(name, bean); } else if (Tokens.SESSION.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean in Session scope"); } request.getSession().setAttribute(name, bean); } else if (Tokens.APPLICATION.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean in Application scope"); } servlet.getServletContext().setAttribute(name, bean); } else if (M2ATokens.CLIENT.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean in Client scope"); } Map beanMap = null; Object attribObj = null; String customerNo = null; String loginKey = null; String sessionKey = null; String customerCountry = null; if (bean != null) { try { beanMap = PropertyUtils.describe(bean); attribObj = beanMap.get(M2ATokens.CUSTOMERNO); if (attribObj != null) { customerNo = (String) attribObj; } attribObj = beanMap.get(M2ATokens.LOGINKEY); if (attribObj != null) { loginKey = (String) attribObj; } attribObj = beanMap.get(M2ATokens.SESSIONKEY); if (attribObj != null) { sessionKey = (String) attribObj; } attribObj = beanMap.get(M2ATokens.CUSTOMERCOUNTRY); if (attribObj != null) { customerCountry = (String) attribObj; } if (log.isDebugEnabled()) { log.debug("*** Cookie value is being set for " + M2ATokens.COOKIE_CUSTOMERNO + " " + customerNo); log.debug( "*** Cookie value is being set for " + M2ATokens.COOKIE_LOGINKEY + " " + loginKey); log.debug("*** Cookie value is being set for " + M2ATokens.COOKIE_SESSIONKEY + " " + sessionKey); log.debug("*** Cookie value is being set for " + M2ATokens.COOKIE_CUSTOMERCOUNTRY + " " + customerCountry); } System.out.println(" CLIENT --> " + customerCountry); String contextPath = request.getContextPath(); M2ACookies.setCookie(response, M2ATokens.COOKIE_CUSTOMERNO, customerNo, contextPath); M2ACookies.setCookie(response, M2ATokens.COOKIE_LOGINKEY, loginKey, contextPath); M2ACookies.setCookie(response, M2ATokens.COOKIE_SESSIONKEY, sessionKey, contextPath); M2ACookies.setCookie(response, M2ATokens.COOKIE_CUSTOMERCOUNTRY, customerCountry, contextPath); /** * Values set into cookies can be read in this same process * When we have 2 process bean and result set returned by the first * process bean used by the second bean then we need to set into form * Set values into the form passed */ if (log.isDebugEnabled()) { log.debug("*** Setting result bean into form"); } M2AFormBase passedForm = (M2AFormBase) form; passedForm.set(bean); } catch (Exception e) { } } } else if (M2ATokens.FORM.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean into form"); } M2AFormBase passedForm = (M2AFormBase) form; try { passedForm.set(bean); } catch (Exception e) { } } else if (M2ATokens.FORM_LIST.equals(scope)) { // 20111212:1 if (log.isDebugEnabled()) { log.debug("*** Setting result bean into form list"); } M2AFormBase passedForm = (M2AFormBase) form; try { passedForm.set(bean, name); } catch (Exception e) { } } else if (M2ATokens.EMPTY.equals(scope)) { if (log.isDebugEnabled()) { log.debug("*** Setting result bean in Empty Scope"); } // do nothing } else { StringBuffer sb = new StringBuffer("exposeInScope: "); sb.append(scope); sb.append(Tokens.INVALID_SCOPE); if (log.isDebugEnabled()) { log.debug("*** " + sb.toString()); } throw new IllegalArgumentException(sb.toString()); } } // end exposeInScope /** * Save result object to servlet context. * <p> * <code>result.getData()</code> must return non-null. * If <code>result.getName()</code> is null, the mapping's attribute * (<code>mapping.getAttribute()</code>) is used in * stead. * By default, this is the <code>form-bean</code>'s name. * <p> * If data is a Collection, only the first element is stored. * * @param mapping The ActionMapping used to select this instance * @param form The ActionForm * @param request The HTTP request we are processing * @param result The ProcessResult we are handling */ protected void checkDataSingle(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ProcessResult result) { if (log.isDebugEnabled()) { log.debug("*** Executing checkDataSingle()"); } String name = result.getName(); if (null == name) { // use form-bean or mapping name name = mapping.getAttribute(); result.setName(name); } if (log.isDebugEnabled()) { log.debug("*** Result name is " + name); } String scope = result.getScope(); Object bean = result.getData(); // if data is collection, use first element if (bean instanceof Collection) { if (log.isDebugEnabled()) { log.debug("*** Result bean is a collection"); } Collection collection = (Collection) bean; if (collection.isEmpty()) { if (log.isDebugEnabled()) { log.debug("*** Result bean is empty, creating new bean instance"); } // for lack of a better idea, get a fresh form-bean // this will return null if there is not a form-bean // associated with this mapping bean = createHelperBean(request, mapping.getName()); } else { if (log.isDebugEnabled()) { log.debug("*** Using first instance of Result bean collection"); } bean = collection.iterator().next(); } } if (result.isExposed()) { exposeInScope(mapping, form, request, response, name, scope, bean); } } // end checkDataSingle /** * Save result object to servlet context. * <p> * <code>result.getData()</code> must return non-null. * If <code>result.getName()</code> is null, the mapping's attribute * (<code>mapping.getAttribute()</code>) is used instead. * By default, this is the <code>form-bean</code>'s name. * * @param mapping The ActionMapping used to select this instance * @param form The ActionForm * @param request The HTTP request we are processing * @param result The ProcessResult we are handling */ protected void checkData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ProcessResult result) { if (log.isDebugEnabled()) { log.debug("*** Executing checkData()"); } if (result.isSingleForm()) { checkDataSingle(mapping, form, request, response, result); } else { String name = result.getName(); if (null == name) { name = Tokens.LIST_KEY; result.setName(name); } if (log.isDebugEnabled()) { log.debug("*** Result name is " + name); } String scope = result.getScope(); Object bean = result.getData(); if (result.isExposed()) { exposeInScope(mapping, form, request, response, name, scope, bean); } } } // end checkData /** * Stores informational messages for display. * * @param mapping The ActionMapping used to select this instance * @param request The HTTP request we are processing * @param processResult The ProcessResult we are handling */ protected void checkMessages(ActionMapping mapping, HttpServletRequest request, ProcessResult processResult) { if (log.isDebugEnabled()) { log.debug("*** Executing checkMessages()"); } saveMessages(request, processResult.getMessages()); } // end checkMessages /** * Process new dispatch advice passed by the business tier. * <p> * This is used to route control to another location besides * the default "success" forward registered with the controller. * * The business tier can pass back either a path or the name of * an ActionForward. * checkDispatch() will then create an ActionForward to return * and save it in the request under the SUCCESS token. * The <code>findSuccess()</code> will check for this attribute * before returning the controller's default. * * @param mapping The ActionMapping used to select this instance * @param request The HTTP request we are processing * @param processResult The ProcessResult we are handling */ protected void checkDispatch(ActionMapping mapping, HttpServletRequest request, ProcessResult processResult) { if (log.isDebugEnabled()) { log.debug("*** Executing checkDispatch()"); } String dispatch = processResult.getDispatch(); ActionForward forward = null; if (log.isDebugEnabled()) { log.debug("*** dispatch to " + dispatch); } if (processResult.isDispatchPath()) { forward = new ActionForward(dispatch); } else { forward = mapping.findForward(dispatch); } // Our findSuccess looks for this request.setAttribute(Tokens.SUCCESS, forward); } // end checkDispatch // --------------------------------------------------------- Public Methods /** * Return the appropriate ActionForward for error or failure * conditions. * First checks for a FAILURE ActionForward stored in the request. * If an override is not found, returns the result of the * superclass method. * * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request * @param request The HTTP request we are processing * @param response The resonse we are creating * @return The ActionForward representing FAILURE * or null if a FAILURE forward has not been specified. */ protected ActionForward findFailure(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { if (log.isDebugEnabled()) { log.debug("*** Executing findFailure()"); } // Did someone leave us a forward? String localeDisplay = ""; ActionForward forward = null; /** * specific mapping is given at ProcessBean * The forward will be to an ActionMapping * The foward given is to a jsp or html, language specific will not be loaded * if required, Tokens.FAILURE should be suffixed with selected locale */ forward = (ActionForward) request.getAttribute(Tokens.FAILURE); if (form instanceof M2AFormBase) { M2AFormBase formBean = (M2AFormBase) form; localeDisplay = formBean.getLocaleLanguage(); } if (null == forward) { if (log.isDebugEnabled()) { log.debug("*** Failure forward is NULL, using default"); } // No override, use default //forward = super.findFailure(mapping, form, request, response); /** * changed on Mar 24 2003 for locale handling */ if (mapping.getInput() != null) { forward = (new ActionForward(mapping.getInput())); } else { // If no input page, use error forwarding forward = mapping.findForward(Tokens.FAILURE + "_" + localeDisplay); } // preprocess check is not needed if forwarded to another action with error request.setAttribute(M2ATokens.PREPROCESS_ERRCHECK, M2ATokens.EMPTY); } else { if (log.isDebugEnabled()) { log.debug("*** Setting Request attribute " + Tokens.FAILURE + " to NULL"); } // Clear advice from the request request.setAttribute(Tokens.FAILURE, null); } return forward; } // end findFailure /** * Optional extension point for pre-processing. * Default method does nothing. * To branch to another URI, return an non-null ActionForward. * If errors are logged (getErrors() et al), * default behaviour will branch to findFailure(). * * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request * @param request The HTTP request we are processing * @param response The resonse we are creating */ protected void preProcess(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { if (log.isDebugEnabled()) { log.debug("*** Executing preProcess()"); } // Check for cancelled ActionForward forward = mapping.findForward(Tokens.CANCEL); if ((null != forward) && (isCancelled(request))) { // Our findFailure looks for this request.setAttribute(Tokens.FAILURE, forward); // Post cancel error message ActionErrors errors = getErrors(request, true); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError(Tokens.ERROR_CANCEL)); return; } // Check for missing token forward = mapping.findForward(Tokens.GET_TOKEN); if ((null != forward) && (!isTokenValid(request))) { // Our findFailure looks for this request.setAttribute(Tokens.FAILURE, forward); // Post token error message ActionErrors errors = getErrors(request, true); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError(Tokens.ERROR_TOKEN)); return; } if (null != forward) { // reset to guard against duplicate request resetToken(request); } // Check for save token directive (do this last) forward = mapping.findForward(Tokens.SET_TOKEN); if (null != forward) saveToken(request); } // end preProcess /** * Check outcome, if any; recurse if container for other outcomes. * * @param mapping The ActionMapping used to select this instance * @param request The HTTP request we are processing * @param result The ProcessResult we are handling */ protected void checkOutcome(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, ProcessResult result) throws Exception { if (log.isDebugEnabled()) { log.debug("*** Executing checkOutcome()"); } if (result != null) { if (result.isAggregate()) { if (log.isDebugEnabled()) { log.debug("*** Result is aggregate i.e. collection of ProcessResult"); } // recurse for each ProcessResult in collection Collection collection = (Collection) result.getData(); Iterator iterator = collection.iterator(); while (iterator.hasNext()) { ProcessResult nextResult = (ProcessResult) iterator.next(); checkOutcome(mapping, form, request, response, nextResult); } } else { if (log.isDebugEnabled()) { log.debug("*** Result is not an aggregate"); } // call extension points for whatever is returned if (result.isData()) checkData(mapping, form, request, response, result); if (result.isMessages()) checkMessages(mapping, request, result); if (result.isDispatch()) checkDispatch(mapping, request, result); } } else { if (log.isDebugEnabled()) { log.debug("*** Result is NULL"); } throw new Exception("ProcessResult is null"); } } // end checkOutcome /** * Return the appropriate ActionForward for the nominal, * non-error state. * First checks for a SUCCESS ActionForward stored in the request. * If an override is not found, returns the result of the * superclass method. * * @param mapping The ActionMapping used to select this instance * @param form The optional ActionForm bean for this request (if any) * @param request The HTTP request we are processing * @param response The response we are creating * @return The ActionForward representing SUCCESS * or null if a SUCCESS forward has not been specified. */ protected ActionForward findSuccess(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { if (log.isDebugEnabled()) { log.debug("*** Executing findSuccess()"); } // Did someone leave us a forward? String localeDisplay = ""; ActionForward forward = null; /** * specific mapping is given at ProcessBean * The forward will be to an ActionMapping * The foward given is to a jsp or html, language specific will not be loaded * if required, Tokens.FAILURE should be suffixed with selected locale */ forward = (ActionForward) request.getAttribute(Tokens.SUCCESS); if (form instanceof M2AFormBase) { M2AFormBase formBean = (M2AFormBase) form; localeDisplay = formBean.getLocaleLanguage(); } if (null == forward) { if (log.isDebugEnabled()) { log.debug("*** forward success is NULL, using default"); } // No override, use default //forward = super.findSuccess(mapping, form, request, response); /** * changed on Mar 24 2003 for locale handling */ if (log.isDebugEnabled()) { log.debug("FindForward for Locale " + localeDisplay); } forward = mapping.findForward(Tokens.SUCCESS + "_" + localeDisplay); } else { if (log.isDebugEnabled()) { log.debug("*** Setting Request attribute " + Tokens.SUCCESS + " to NULL"); } // Clear advice from the request request.setAttribute(Tokens.SUCCESS, null); } return forward; } // end findSuccess /** * Retrieve from session under known key * (<code>ProcessBean.USER_PROFILE_KEY</code>). * Override this approach to implement another method (e.g cookies). * Also revise UpdateProfile action-mapping to store changes. * * @param mapping The ActionMapping used to select this instance * @param form The ActionForm * @param request The HTTP request we are processing * @param response The HTTP response we are creating */ protected Map getUserProfile(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { /** * read Session info from Cookie and set into M2AFormBase */ if (log.isDebugEnabled()) { log.debug("*** Executing getUserProfile()"); } M2AFormBase profileForm = null; Map userMap = null; profileForm = (M2AFormBase) request.getSession().getAttribute(ProcessBean.USER_PROFILE_KEY); if (profileForm == null) { if (log.isDebugEnabled()) { log.debug("*** UserProfile form is NULL, creating an empty properties map"); } userMap = new HashMap(); } else { if (log.isDebugEnabled()) { log.debug("*** creating UserProfile map"); } userMap = profileForm.describe(); } if (log.isDebugEnabled()) { log.debug("*** Reading values from Cookie"); } String customerNo = M2ACookies.getCookie(request, M2ATokens.COOKIE_CUSTOMERNO); String loginKey = M2ACookies.getCookie(request, M2ATokens.COOKIE_LOGINKEY); String sessionKey = M2ACookies.getCookie(request, M2ATokens.COOKIE_SESSIONKEY); String customerCountry = M2ACookies.getCookie(request, M2ATokens.COOKIE_CUSTOMERCOUNTRY); if (log.isDebugEnabled()) { log.debug("*** Cookie values are being set in UserProfile map"); log.debug("*** Read value from Cookie, " + M2ATokens.COOKIE_CUSTOMERNO + " " + customerNo); log.debug("*** Read value from Cookie, " + M2ATokens.COOKIE_LOGINKEY + " " + loginKey); log.debug("*** Read value from Cookie, " + M2ATokens.COOKIE_SESSIONKEY + " " + sessionKey); log.debug("*** Read value from Cookie, " + M2ATokens.COOKIE_CUSTOMERCOUNTRY + " " + customerCountry); } /** * set Session info in the form */ userMap.put(M2ATokens.CUSTOMERNO, customerNo); userMap.put(M2ATokens.LOGINKEY, loginKey); userMap.put(M2ATokens.SESSIONKEY, sessionKey); userMap.put(M2ATokens.CUSTOMERCOUNTRY, customerCountry); return userMap; } // end getUserProfile /** * Assume that helpers are ProcessBeans, execute each, and * process outcome. * * @param mapping The ActionMapping used to select this instance * @param form The ActionForm * @param request The HTTP request we are processing * @param response The HTTP response we are creating * @param helpers The object instantiated from type given as parameter. * @exception IOException if an input/output error occurs * @exception ServletException if a servlet exception occurs */ protected void executeLogic(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, Object[] helpers) throws Exception { if (log.isDebugEnabled()) { log.debug("*** Executing executeLogic()"); } // Retrieve user profile, if any Map userMap = getUserProfile(mapping, form, request, response); if ((null != userMap) && (null != form)) { if (log.isDebugEnabled()) { log.debug("*** Merging UserProfile values with passed form"); } BeanUtils.copyProperties(form, userMap); System.err.println("REACHED" + userMap.get("customerCountry")); } if (log.isDebugEnabled()) { log.debug("*** Ready to process ProcessBeans"); } Map properties = null; for (int i = 0; i < helpers.length; i++) { if (log.isDebugEnabled()) { log.debug("*** Processing ProcessBean number " + i); } // Get helper instantiated by ancestor ProcessBean dataBean = (ProcessBean) helpers[i]; properties = null; if (null != form) { if (form instanceof M2AFormBase) { if (log.isDebugEnabled()) { log.debug("*** Form is an instance of M2AFormBase, setting SessionLocale"); } M2AFormBase formBean = (M2AFormBase) form; // Pass up the Locale dataBean.setLocale(formBean.getSessionLocale()); } if (log.isDebugEnabled()) { log.debug("*** Converting form data as properties map"); } properties = PropertyUtils.describe(form); } // end null form else if (null != userMap) { // if no form, but is profile, still use profile properties = userMap; } if (log.isDebugEnabled()) { log.debug("*** Setting value for RemoteServer"); } // Pass up the RemoteServer (if any) dataBean.setRemoteServer(getRemoteServer()); // Execute business logic, using values from map if (log.isDebugEnabled()) { log.debug("*** Ready to execute business logic in ProcessBean"); } ProcessResult result = (ProcessResult) dataBean.execute(properties); if (log.isDebugEnabled()) { log.debug("*** Ready to process ProcessResult from ProcessBean"); } // Analyze result of business logic checkOutcome(mapping, form, request, response, result); } // end for } // end executeLogic public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // Check for precondition errors; fail if found preProcess(mapping, form, request, response); if (isPreProcessErrCheck(request)) { if (isErrors(request)) { return findFailure(mapping, form, request, response); } } // Try the logic; Call catchException() if needed try { executeLogic(mapping, form, request, response); } catch (Exception e) { // Store Exception; call extension point setException(request, e); catchException(mapping, form, request, response); } finally { postProcess(mapping, form, request, response); } // If errors queued, fail if (isErrors(request)) { return findFailure(mapping, form, request, response); } // Otherwise, check for messages and succeed (only 1_0) /* if ((isStruts_1_0()) && (isMessages(request))) { saveErrors(request,getMessages(request,false)); } */ return findSuccess(mapping, form, request, response); } // end execute() /** * Check whether preProcess() error handling need to be done * or not */ protected boolean isPreProcessErrCheck(HttpServletRequest request) { if (log.isDebugEnabled()) { log.debug("*** Checking for the preProcess error handling"); } return (null == request.getAttribute(M2ATokens.PREPROCESS_ERRCHECK)); } /** * Added for eliminating java error text in the DB error message */ protected void catchException(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { Exception exception = getException(request); exception.printStackTrace(); ActionErrors errors = getErrors(request, true); //errors.add("org.apache.struts.action.GLOBAL_ERROR",new ActionError("error.general")); StringBuffer sb = new StringBuffer(); if (exception instanceof BaseException) { BaseException e = (BaseException) exception; e.getMessage(sb); sb.delete(0, 74); } else { sb.append('\r'); //sb.append("ERROR: "); //20120528:1 //sb.append(exception.toString()); String message = exception.getMessage(); if (null != message) { //sb.append('\r'); //sb.append(" DETAILS: "); sb.append(message); //sb.append('\r'); } // if (null } // if (exception errors.add("org.apache.struts.action.GLOBAL_ERROR", new ActionError("error.detail", sb.toString())); } // catch } // end M2AProcessBridgeAction /* * * Copyright (c) 2002 Synthis Corporation. * 430 10th Street NW, Suite S-108, Atlanta GA 30318, U.S.A. * All rights reserved. * * This software is licensed to you free of charge under * the Apache Software License, so long as this copyright * statement, list of conditions, and comments, remains * in the source code. See bottom of file for more * license information. * * This software was written to support code generation * for the Apache Struts J2EE architecture by Synthis' * visual application modeling tool Adalon. * * For more information on Adalon and Struts code * generation please visit http://www.synthis.com * */ /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Scaffold", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */