1 /**
2 *
3 */
4 package ar.com.jiji.kaya.spring;
5
6 import java.util.Iterator;
7 import java.util.Map;
8 import java.util.Set;
9
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.hibernate.HibernateException;
13 import org.hibernate.SessionFactory;
14 import org.springframework.beans.BeansException;
15 import org.springframework.beans.FatalBeanException;
16 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
17 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
18
19 import ar.com.jiji.kaya.KayaException;
20 import ar.com.jiji.kaya.KayaRuntimeException;
21 import ar.com.jiji.kaya.reflect.MethodNames;
22 import ar.com.jiji.kaya.reflect.ReflectionException;
23 import ar.com.jiji.kaya.reflect.ReflectionService;
24 import ar.com.jiji.kaya.utils.ValidateUtils;
25
26 /**
27 * Trata de descubrir implementaciones de daos a partir de las clases mapeadas
28 * en Hibernate y setearlos a los objetos que se desea (si existen los setters).
29 *
30 * TODO: escribir mas docs
31 *
32 * @author lparra
33 * @version $Revision$ $Date$
34 */
35 public class DaoAutoWirer implements BeanFactoryPostProcessor {
36 private static final Log log = LogFactory.getLog(DaoAutoWirer.class);
37
38 private SessionFactory sessionFactory;
39
40 private String daoPackage = "dao";
41
42 private String daoImplPackage = "dao.hib";
43
44 private String daoSuffix = "Dao";
45
46 private String daoImplSuffix = "DaoImpl";
47
48 private boolean failOnMissingDaoSetter = false;
49
50 private boolean failOnMissingDaoImpl = false;
51
52 private Set objects;
53
54 private DaoInstantiator daoInstantiator;
55
56 public DaoAutoWirer() {
57 setDaoInstantiator(new SimpleDaoInstantiator());
58 }
59
60 public boolean isFailOnMissingDaoImpl() {
61 return failOnMissingDaoImpl;
62 }
63
64 public void setFailOnMissingDaoImpl(boolean failOnMissingDaoImpl) {
65 this.failOnMissingDaoImpl = failOnMissingDaoImpl;
66 }
67
68 public String getDaoImplSuffix() {
69 return daoImplSuffix;
70 }
71
72 public void setDaoImplSuffix(String daoImplSuffix) {
73 this.daoImplSuffix = daoImplSuffix;
74 }
75
76 public String getDaoSuffix() {
77 return daoSuffix;
78 }
79
80 public void setDaoSuffix(String daoSuffix) {
81 this.daoSuffix = daoSuffix;
82 }
83
84 public String getDaoPackage() {
85 return daoPackage;
86 }
87
88 public void setDaoPackage(String daoPackage) {
89 this.daoPackage = daoPackage;
90 }
91
92 public SessionFactory getSessionFactory() {
93 return sessionFactory;
94 }
95
96 public void setSessionFactory(SessionFactory sessionFactory) {
97 this.sessionFactory = sessionFactory;
98 }
99
100 protected void populateObjects(Set objects) throws BeansException {
101 ValidateUtils.notNull(objects);
102
103 if (getSessionFactory() == null)
104 throw new FatalBeanException("No session factory set");
105
106 Map metadata;
107 try {
108 metadata = this.sessionFactory.getAllClassMetadata();
109 } catch (HibernateException e) {
110 throw new FatalBeanException("Collecting metadata", e);
111 }
112 for (Iterator i = metadata.keySet().iterator(); i.hasNext();) {
113 String className = (String) i.next();
114 String modelPkg;
115 String modelName;
116 String daoPkg, daoImplPkg;
117 int pos;
118
119 pos = className.lastIndexOf('.');
120 if (pos == -1) {
121 modelPkg = "";
122 modelName = className;
123 } else {
124 modelPkg = className.substring(0, pos);
125 modelName = className.substring(pos + 1);
126 }
127
128 log.info("searching dao for mapped class " + className);
129
130 pos = modelPkg.lastIndexOf('.');
131 if (pos == -1) {
132 log.info("default package for " + modelName
133 + ", searching dao there.");
134 daoImplPkg = daoPkg = "";
135 } else {
136 daoImplPkg = modelPkg.substring(0, pos + 1)
137 + getDaoImplPackage() + ".";
138 daoPkg = modelPkg.substring(0, pos + 1) + getDaoPackage() + ".";
139 }
140
141 String clazzImpl = daoImplPkg + modelName + getDaoImplSuffix();
142 String classInterface = daoPkg + modelName + getDaoSuffix();
143
144 Object dao = null;
145 try {
146 dao = newDaoInstance(clazzImpl, classInterface);
147 log.info("found dao " + clazzImpl + " for " + className);
148 } catch (KayaException e) {
149 throw new KayaRuntimeException(e);
150 } catch (ClassNotFoundException e) {
151 if (isFailOnMissingDaoImpl()) {
152 throw new KayaRuntimeException(e);
153 }
154 log.info("dao " + clazzImpl + " not found for " + className);
155 }
156
157 if (dao != null) {
158 try {
159 initDao(dao);
160 for (Object o : objects)
161 setDao(o, dao, classInterface);
162 } catch (KayaException e) {
163 throw new FatalBeanException("", e);
164 } catch (NoSuchMethodException e) {
165 if (isFailOnMissingDaoSetter()) {
166
167 throw new RuntimeException(e);
168 }
169 log
170 .info("object doesn't have setter for "
171 + classInterface);
172 }
173 }
174 }
175 }
176
177 private void setDao(Object obj, Object dao, String interfaceName)
178 throws KayaException, NoSuchMethodException {
179 try {
180 Class interfaceClazz = Class.forName(interfaceName);
181 ReflectionService.invoke(MethodNames.getDaoMutator(interfaceClazz),
182 interfaceClazz, obj, dao);
183 log.info("set " + interfaceName);
184 } catch (SecurityException e) {
185 throw new KayaException(e);
186 } catch (ReflectionException e) {
187 if (e.getCause() instanceof NoSuchMethodException) {
188 if (isFailOnMissingDaoSetter())
189 throw new KayaException(e);
190 } else
191 throw new KayaException(e);
192 } catch (ClassNotFoundException e) {
193 throw new KayaException(e);
194 }
195 }
196
197 private void initDao(Object dao) throws KayaException,
198 NoSuchMethodException {
199 setSessionFactory(dao);
200 }
201
202 private void setSessionFactory(Object dao) throws KayaException,
203 NoSuchMethodException {
204
205 try {
206 ReflectionService.invoke(MethodNames.getMutator("sessionFactory"),
207 SessionFactory.class, dao, getSessionFactory());
208 } catch (SecurityException e) {
209 throw new KayaException(e);
210 } catch (IllegalArgumentException e) {
211 throw new KayaException(e);
212 } catch (ReflectionException e) {
213 throw new KayaException(e);
214 }
215 }
216
217 private Object newDaoInstance(String clazzImpl, String classInterface)
218 throws KayaException, ClassNotFoundException {
219 try {
220 return getDaoInstantiator().instantiate(clazzImpl, classInterface);
221 } catch (InstantiationException e) {
222 throw new KayaException(e);
223 } catch (IllegalAccessException e) {
224 throw new KayaException(e);
225 }
226 }
227
228 public String getDaoImplPackage() {
229 return daoImplPackage;
230 }
231
232 public void setDaoImplPackage(String daoImplPackage) {
233 this.daoImplPackage = daoImplPackage;
234 }
235
236 public boolean isFailOnMissingDaoSetter() {
237 return failOnMissingDaoSetter;
238 }
239
240 public void setFailOnMissingDaoSetter(boolean failOnMissingDaoSetter) {
241 this.failOnMissingDaoSetter = failOnMissingDaoSetter;
242 }
243
244 public void postProcessBeanFactory(
245 ConfigurableListableBeanFactory beanFactory) throws BeansException {
246 populateObjects(getObjects());
247 }
248
249 public Set getObjects() {
250 return objects;
251 }
252
253 public void setObjects(Set objects) {
254 this.objects = objects;
255 }
256
257 public DaoInstantiator getDaoInstantiator() {
258 return daoInstantiator;
259 }
260
261 public void setDaoInstantiator(DaoInstantiator daoInstantiator) {
262 this.daoInstantiator = daoInstantiator;
263 }
264
265 }