View Javadoc

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 						// TODO crear alguna excepcion
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 		// TODO: tal vez spring tenga algo ya para esto
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 }