Source Code Cross Referenced for SpringBindingActionForm.java in  » J2EE » spring-framework-2.0.6 » org » springframework » web » struts » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.web.struts 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2006 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.web.struts;
018:
019:        import java.lang.reflect.InvocationTargetException;
020:        import java.util.Iterator;
021:        import java.util.Locale;
022:
023:        import javax.servlet.http.HttpServletRequest;
024:
025:        import org.apache.commons.beanutils.BeanUtilsBean;
026:        import org.apache.commons.beanutils.ConvertUtilsBean;
027:        import org.apache.commons.beanutils.PropertyUtilsBean;
028:        import org.apache.commons.logging.Log;
029:        import org.apache.commons.logging.LogFactory;
030:        import org.apache.struts.Globals;
031:        import org.apache.struts.action.ActionForm;
032:        import org.apache.struts.action.ActionMessage;
033:        import org.apache.struts.action.ActionMessages;
034:        import org.apache.struts.util.MessageResources;
035:
036:        import org.springframework.context.MessageSourceResolvable;
037:        import org.springframework.validation.Errors;
038:        import org.springframework.validation.FieldError;
039:        import org.springframework.validation.ObjectError;
040:
041:        /**
042:         * A thin Struts ActionForm adapter that delegates to Spring's more complete
043:         * and advanced data binder and Errors object underneath the covers to bind
044:         * to POJOs and manage rejected values.
045:         *
046:         * <p>Exposes Spring-managed errors to the standard Struts view tags, through
047:         * exposing a corresponding Struts ActionMessages object as request attribute.
048:         * Also exposes current field values in a Struts-compliant fashion, including
049:         * rejected values (which Spring's binding keeps even for non-String fields).
050:         *
051:         * <p>Consequently, Struts views can be written in a completely traditional
052:         * fashion (with standard <code>html:form</code>, <code>html:errors</code>, etc),
053:         * seamlessly accessing a Spring-bound POJO form object underneath.
054:         *
055:         * <p>Note this ActionForm is designed explicitly for use in <i>request scope</i>.
056:         * It expects to receive an <code>expose</code> call from the Action, passing
057:         * in the Errors object to expose plus the current HttpServletRequest.
058:         *
059:         * <p>Example definition in <code>struts-config.xml</code>:
060:         *
061:         * <pre>
062:         * &lt;form-beans&gt;
063:         *   &lt;form-bean name="actionForm" type="org.springframework.web.struts.SpringBindingActionForm"/&gt;
064:         * &lt;/form-beans&gt;</pre>
065:         * 
066:         * Example code in a custom Struts <code>Action</code>:
067:         *
068:         * <pre>
069:         * public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception {
070:         *   SpringBindingActionForm form = (SpringBindingActionForm) actionForm;
071:         *   MyPojoBean bean = ...;
072:         *   ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, "myPojo");
073:         *   binder.bind(request);
074:         *   form.expose(binder.getBindingResult(), request);
075:         *   return actionMapping.findForward("success");
076:         * }</pre>
077:         *
078:         * This class is compatible with both Struts 1.2.x and Struts 1.1.
079:         * On Struts 1.2, default messages registered with Spring binding errors
080:         * are exposed when none of the error codes could be resolved.
081:         * On Struts 1.1, this is not possible due to a limitation in the Struts
082:         * message facility; hence, we expose the plain default error code there.
083:         *
084:         * @author Keith Donald
085:         * @author Juergen Hoeller
086:         * @since 1.2.2
087:         * @see #expose(org.springframework.validation.Errors, javax.servlet.http.HttpServletRequest)
088:         */
089:        public class SpringBindingActionForm extends ActionForm {
090:
091:            private static final Log logger = LogFactory
092:                    .getLog(SpringBindingActionForm.class);
093:
094:            private static boolean defaultActionMessageAvailable = true;
095:
096:            static {
097:                // Register special PropertyUtilsBean subclass that knows how to
098:                // extract field values from a SpringBindingActionForm.
099:                // As a consequence of the static nature of Commons BeanUtils,
100:                // we have to resort to this initialization hack here.
101:                ConvertUtilsBean convUtils = new ConvertUtilsBean();
102:                PropertyUtilsBean propUtils = new SpringBindingAwarePropertyUtilsBean();
103:                BeanUtilsBean beanUtils = new BeanUtilsBean(convUtils,
104:                        propUtils);
105:                BeanUtilsBean.setInstance(beanUtils);
106:
107:                // Determine whether the Struts 1.2 support for default messages
108:                // is available on ActionMessage: ActionMessage(String, boolean)
109:                // with "false" to be passed into the boolean flag.
110:                try {
111:                    ActionMessage.class.getConstructor(new Class[] {
112:                            String.class, boolean.class });
113:                } catch (NoSuchMethodException ex) {
114:                    defaultActionMessageAvailable = false;
115:                }
116:            }
117:
118:            private Errors errors;
119:
120:            private Locale locale;
121:
122:            private MessageResources messageResources;
123:
124:            /**
125:             * Set the Errors object that this SpringBindingActionForm is supposed
126:             * to wrap. The contained field values and errors will be exposed
127:             * to the view, accessible through Struts standard tags.
128:             * @param errors the Spring Errors object to wrap, usually taken from
129:             * a DataBinder that has been used for populating a POJO form object
130:             * @param request the HttpServletRequest to retrieve the attributes from
131:             * @see org.springframework.validation.DataBinder#getBindingResult()
132:             */
133:            public void expose(Errors errors, HttpServletRequest request) {
134:                this .errors = errors;
135:
136:                // Obtain the locale from Struts well-known location.
137:                this .locale = (Locale) request.getSession().getAttribute(
138:                        Globals.LOCALE_KEY);
139:
140:                // Obtain the MessageResources from Struts' well-known location.
141:                this .messageResources = (MessageResources) request
142:                        .getAttribute(Globals.MESSAGES_KEY);
143:
144:                if (errors != null && errors.hasErrors()) {
145:                    // Add global ActionError instances from the Spring Errors object.
146:                    ActionMessages actionMessages = (ActionMessages) request
147:                            .getAttribute(Globals.ERROR_KEY);
148:                    if (actionMessages == null) {
149:                        request.setAttribute(Globals.ERROR_KEY,
150:                                getActionMessages());
151:                    } else {
152:                        actionMessages.add(getActionMessages());
153:                    }
154:                }
155:            }
156:
157:            /**
158:             * Return an ActionMessages representation of this SpringBindingActionForm,
159:             * exposing all errors contained in the underlying Spring Errors object.
160:             * @see org.springframework.validation.Errors#getAllErrors()
161:             */
162:            private ActionMessages getActionMessages() {
163:                ActionMessages actionMessages = new ActionMessages();
164:                Iterator it = this .errors.getAllErrors().iterator();
165:                while (it.hasNext()) {
166:                    ObjectError objectError = (ObjectError) it.next();
167:                    String effectiveMessageKey = findEffectiveMessageKey(objectError);
168:                    if (effectiveMessageKey == null
169:                            && !defaultActionMessageAvailable) {
170:                        // Need to specify default code despite it not being resolvable:
171:                        // Struts 1.1 ActionMessage doesn't support default messages.
172:                        effectiveMessageKey = objectError.getCode();
173:                    }
174:                    ActionMessage message = (effectiveMessageKey != null) ? new ActionMessage(
175:                            effectiveMessageKey, resolveArguments(objectError
176:                                    .getArguments()))
177:                            : new ActionMessage(
178:                                    objectError.getDefaultMessage(), false);
179:                    if (objectError instanceof  FieldError) {
180:                        FieldError fieldError = (FieldError) objectError;
181:                        actionMessages.add(fieldError.getField(), message);
182:                    } else {
183:                        actionMessages.add(ActionMessages.GLOBAL_MESSAGE,
184:                                message);
185:                    }
186:                }
187:                if (logger.isDebugEnabled()) {
188:                    logger.debug("Final ActionMessages used for binding: "
189:                            + actionMessages);
190:                }
191:                return actionMessages;
192:            }
193:
194:            private Object[] resolveArguments(Object[] arguments) {
195:                if (arguments == null || arguments.length == 0) {
196:                    return arguments;
197:                }
198:                for (int i = 0; i < arguments.length; i++) {
199:                    Object arg = arguments[i];
200:                    if (arg instanceof  MessageSourceResolvable) {
201:                        MessageSourceResolvable resolvable = (MessageSourceResolvable) arg;
202:                        String[] codes = resolvable.getCodes();
203:                        boolean resolved = false;
204:                        if (this .messageResources != null) {
205:                            for (int j = 0; j < codes.length; j++) {
206:                                String code = codes[j];
207:                                if (this .messageResources.isPresent(
208:                                        this .locale, code)) {
209:                                    arguments[i] = this .messageResources
210:                                            .getMessage(this .locale, code,
211:                                                    resolveArguments(resolvable
212:                                                            .getArguments()));
213:                                    resolved = true;
214:                                    break;
215:                                }
216:                            }
217:                        }
218:                        if (!resolved) {
219:                            arguments[i] = resolvable.getDefaultMessage();
220:                        }
221:                    }
222:                }
223:                return arguments;
224:            }
225:
226:            /**
227:             * Find the most specific message key for the given error.
228:             * @param error the ObjectError to find a message key for
229:             * @return the most specific message key found
230:             */
231:            private String findEffectiveMessageKey(ObjectError error) {
232:                if (this .messageResources != null) {
233:                    String[] possibleMatches = error.getCodes();
234:                    for (int i = 0; i < possibleMatches.length; i++) {
235:                        if (logger.isDebugEnabled()) {
236:                            logger.debug("Looking for error code '"
237:                                    + possibleMatches[i] + "'");
238:                        }
239:                        if (this .messageResources.isPresent(this .locale,
240:                                possibleMatches[i])) {
241:                            if (logger.isDebugEnabled()) {
242:                                logger.debug("Found error code '"
243:                                        + possibleMatches[i]
244:                                        + "' in resource bundle");
245:                            }
246:                            return possibleMatches[i];
247:                        }
248:                    }
249:                }
250:                if (logger.isDebugEnabled()) {
251:                    logger
252:                            .debug("Could not find a suitable message error code, returning default message");
253:                }
254:                return null;
255:            }
256:
257:            /**
258:             * Get the formatted value for the property at the provided path.
259:             * The formatted value is a string value for display, converted
260:             * via a registered property editor.
261:             * @param propertyPath the property path
262:             * @return the formatted property value
263:             * @throws NoSuchMethodException if called during Struts binding
264:             * (without Spring Errors object being exposed), to indicate no
265:             * available property to Struts
266:             */
267:            private Object getFieldValue(String propertyPath)
268:                    throws NoSuchMethodException {
269:                if (this .errors == null) {
270:                    throw new NoSuchMethodException(
271:                            "No bean properties exposed to Struts binding - performing Spring binding later on");
272:                }
273:                return this .errors.getFieldValue(propertyPath);
274:            }
275:
276:            /**
277:             * Special subclass of PropertyUtilsBean that it is aware of SpringBindingActionForm
278:             * and uses it for retrieving field values. The field values will be taken from
279:             * the underlying POJO form object that the Spring Errors object was created for.
280:             */
281:            private static class SpringBindingAwarePropertyUtilsBean extends
282:                    PropertyUtilsBean {
283:
284:                public Object getNestedProperty(Object bean, String propertyPath)
285:                        throws IllegalAccessException,
286:                        InvocationTargetException, NoSuchMethodException {
287:
288:                    // Extract Spring-managed field value in case of SpringBindingActionForm.
289:                    if (bean instanceof  SpringBindingActionForm) {
290:                        SpringBindingActionForm form = (SpringBindingActionForm) bean;
291:                        return form.getFieldValue(propertyPath);
292:                    }
293:
294:                    // Else fall back to default PropertyUtils behavior.
295:                    return super.getNestedProperty(bean, propertyPath);
296:                }
297:            }
298:
299:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.