Source code: org/mentawai/filter/InjectionFilter.java
1 /*
2 * Mentawai Web Framework http://mentawai.lohis.com.br/
3 * Copyright (C) 2005 Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 package org.mentawai.filter;
20
21 import java.lang.reflect.*;
22 import java.util.*;
23
24 import org.mentawai.core.*;
25 import org.mentawai.util.*;
26
27 /**
28 * A filter that tries to inject the input values in the action through setters. (Ex. <i>setUsername()</i>, <i>setPassword()</i>, etc.)
29 * It can also inject the input value directly in the attribute, even if it is a private field.
30 * Use this filter if you don't want to deal with the action input object and instaed you want to inject its values in the action.
31 * This filter tries to inject all the input values in the action.
32 *
33 * @author Sergio Oliveira
34 */
35 public class InjectionFilter implements Filter {
36
37 private Map methods = new HashMap();
38 private boolean tryField = false;
39
40 /**
41 * Creates an InjectionFilter that can be used by any action class.
42 * You may use this filter per action or as a global filter.
43 */
44 public InjectionFilter() { }
45
46 /**
47 * Creates an InjectionFilter that can be used by any action class.
48 * You may use this filter per action or as a global filter.
49 * If tryField is true and it cannot find a setter for the input value,
50 * it will try to directly access the attribute, even if it is a private field.
51 *
52 * @param tryField A flag indicating whether this filter should try to access private attributes.
53 */
54 public InjectionFilter(boolean tryField) {
55 this.tryField = tryField;
56 }
57
58 /*
59 * Find a field, even if it is private...
60 */
61 static Field getField(Object target, String name) {
62 Field fields[] = target.getClass().getDeclaredFields();
63 for(int i=0;i<fields.length;i++) {
64 if (name.equals(fields[i].getName())) {
65 return fields[i];
66 }
67 }
68 return null;
69 }
70
71 /*
72 * Use reflection to inject the value in the action.
73 */
74 private void setValue(Object target, String name, Object value) {
75 try {
76 StringBuffer sb = new StringBuffer(30);
77 sb.append("set");
78 sb.append(name.substring(0,1).toUpperCase());
79 if (name.length() > 1) sb.append(name.substring(1));
80
81 String methodName = sb.toString();
82
83 Class actionClass = target.getClass();
84
85 Map map = (Map) methods.get(actionClass);
86 if (map == null) {
87 map = new HashMap();
88 methods.put(actionClass, map);
89 }
90
91 if (!map.containsKey(name)) {
92 Method m = null;
93 Field f = null;
94 try {
95 //m = actionClass.getMethod(methodName, new Class[] { value.getClass() });
96 m = FindMethod.getMethod(actionClass, methodName, new Class[] { value.getClass() });
97 } catch(Exception e) {
98 //e.printStackTrace();
99
100 // try primitive...
101 Class primitive = getPrimitiveFrom(value);
102 if (primitive != null) {
103 try {
104 m = actionClass.getMethod(methodName, new Class[] { primitive });
105 } catch(Exception ex) {
106 //ex.printStackTrace();
107 }
108 }
109
110 if (m == null && tryField) {
111 // try field...
112 f = getField(target, name);
113 if (f != null) {
114 f.setAccessible(true);
115 }
116 }
117
118 }
119 if (m != null) {
120 map.put(name, m);
121 m.setAccessible(true);
122 } else {
123 map.put(name, f);
124 }
125 }
126
127 Object obj = map.get(name);
128 if (obj instanceof Method) {
129 Method m = (Method) obj;
130 m.invoke(target, new Object[] { value });
131 } else if (obj instanceof Field) {
132 Field f = (Field) obj;
133 f.set(target, value);
134 }
135 } catch(Exception e) {
136 //e.printStackTrace();
137 }
138 }
139
140 static Class getPrimitiveFrom(Object w) {
141 if (w instanceof Boolean) { return Boolean.TYPE; }
142 else if (w instanceof Byte) { return Byte.TYPE; }
143 else if (w instanceof Short) { return Short.TYPE; }
144 else if (w instanceof Character) { return Character.TYPE; }
145 else if (w instanceof Integer) { return Integer.TYPE; }
146 else if (w instanceof Long) { return Long.TYPE; }
147 else if (w instanceof Float) { return Float.TYPE; }
148 else if (w instanceof Double) { return Double.TYPE; }
149 return null;
150 }
151
152 public String filter(InvocationChain chain) throws Exception {
153 Action action = chain.getAction();
154
155 Object model = null;
156 // model-driven...
157 if (action instanceof ModelDriven) {
158 ModelDriven md = (ModelDriven) action;
159 model = md.getModel();
160 if (model == null) throw new FilterException("ModelDriven action cannot return a null model!");
161 }
162
163 Input input = action.getInput();
164 Iterator iter = input.keys();
165 while(iter.hasNext()) {
166 String name = (String) iter.next();
167 Object value = input.getValue(name);
168 if (value == null) continue;
169 if (model != null) {
170 setValue(model, name, value);
171 } else {
172 setValue(action, name, value);
173 }
174 }
175 return chain.invoke();
176 }
177
178 public void destroy() { }
179 }
180