1 16 package com.ibatis.dao.engine.builder.xml; 17 18 import com.ibatis.common.io.ReaderInputStream; 19 import com.ibatis.common.resources.Resources; 20 import com.ibatis.common.exception.NestedRuntimeException; 21 import com.ibatis.dao.client.Dao; 22 import com.ibatis.dao.client.DaoException; 23 import com.ibatis.dao.client.DaoManager; 24 import com.ibatis.dao.engine.impl.DaoContext; 25 import com.ibatis.dao.engine.impl.DaoImpl; 26 import com.ibatis.dao.engine.impl.StandardDaoManager; 27 import com.ibatis.dao.engine.transaction.DaoTransactionManager; 28 import com.ibatis.dao.engine.transaction.external.ExternalDaoTransactionManager; 29 import com.ibatis.dao.engine.transaction.hibernate.HibernateDaoTransactionManager; 30 import com.ibatis.dao.engine.transaction.jdbc.JdbcDaoTransactionManager; 31 import com.ibatis.dao.engine.transaction.jta.JtaDaoTransactionManager; 32 import com.ibatis.dao.engine.transaction.sqlmap.SqlMapDaoTransactionManager; 33 import org.w3c.dom.*; 34 import org.xml.sax.ErrorHandler ; 35 import org.xml.sax.SAXException ; 36 import org.xml.sax.SAXParseException ; 37 38 import javax.xml.parsers.DocumentBuilder ; 39 import javax.xml.parsers.DocumentBuilderFactory ; 40 import java.io.IOException ; 41 import java.io.OutputStreamWriter ; 42 import java.io.PrintWriter ; 43 import java.io.Reader ; 44 import java.lang.reflect.Constructor ; 45 import java.util.HashMap ; 46 import java.util.Map ; 47 import java.util.Properties ; 48 49 52 public class XmlDaoManagerBuilder { 53 54 55 private static final String DAO_CONFIG_ELEMENT = "daoConfig"; 56 private static final String PROPERTIES_ELEMENT = "properties"; 57 private static final String CONTEXT_ELEMENT = "context"; 58 private static final String TRANS_MGR_ELEMENT = "transactionManager"; 59 private static final String PROPERTY_ELEMENT = "property"; 60 private static final String DAO_ELEMENT = "dao"; 61 62 private Properties properties = null; 63 private boolean validationEnabled = true; 64 private Map typeAliases = new HashMap (); 65 66 public XmlDaoManagerBuilder() { 67 typeAliases.put("JDBC", JdbcDaoTransactionManager.class.getName()); 68 typeAliases.put("JTA", JtaDaoTransactionManager.class.getName()); 69 typeAliases.put("EXTERNAL", ExternalDaoTransactionManager.class.getName()); 70 typeAliases.put("HIBERNATE", HibernateDaoTransactionManager.class.getName()); 71 typeAliases.put("SQLMAP", SqlMapDaoTransactionManager.class.getName()); 72 } 73 74 public DaoManager buildDaoManager(Reader reader, Properties props) 75 throws DaoException { 76 properties = props; 77 return buildDaoManager(reader); 78 } 79 80 public DaoManager buildDaoManager(Reader reader) 81 throws DaoException { 82 StandardDaoManager daoManager = new StandardDaoManager(); 83 84 try { 85 86 Document doc = getDoc(reader); 87 Element root = (Element) doc.getLastChild(); 88 89 String rootname = root.getNodeName(); 90 if (!DAO_CONFIG_ELEMENT.equals(rootname)) { 91 throw new IOException ("Error while configuring DaoManager. The root tag of the DAO configuration XML " + 92 "document must be '" + DAO_CONFIG_ELEMENT + "'."); 93 } 94 95 NodeList children = root.getChildNodes(); 96 for (int i = 0; i < children.getLength(); i++) { 97 Node child = children.item(i); 98 if (child.getNodeType() == Node.ELEMENT_NODE) { 99 if (CONTEXT_ELEMENT.equals(child.getNodeName())) { 100 DaoContext daoContext = parseContext((Element) child, daoManager); 101 daoManager.addContext(daoContext); 102 } else if (PROPERTIES_ELEMENT.equals(child.getNodeName())) { 103 Properties attributes = parseAttributes(child); 104 if (attributes.containsKey("resource")) { 105 String resource = attributes.getProperty("resource"); 106 if (properties == null) { 107 properties = Resources.getResourceAsProperties(resource); 108 } else { 109 Properties tempProps = Resources.getResourceAsProperties(resource); 110 tempProps.putAll(properties); 111 properties = tempProps; 112 } 113 } else if (attributes.containsKey("url")) { 114 String url = attributes.getProperty("url"); 115 if (properties == null) { 116 properties = Resources.getUrlAsProperties(url); 117 } else { 118 Properties tempProps = Resources.getUrlAsProperties(url); 119 tempProps.putAll(properties); 120 properties = tempProps; 121 } 122 } 123 } 124 } 125 } 126 } catch (Exception e) { 127 throw new DaoException("Error while configuring DaoManager. Cause: " + e.toString(), e); 128 } 129 return daoManager; 130 } 131 132 public boolean isValidationEnabled() { 133 return validationEnabled; 134 } 135 136 public void setValidationEnabled(boolean validationEnabled) { 137 this.validationEnabled = validationEnabled; 138 } 139 140 private DaoContext parseContext(Element contextElement, StandardDaoManager daoManager) 141 throws DaoException { 142 DaoContext daoContext = new DaoContext(); 143 144 daoContext.setDaoManager(daoManager); 145 String id = contextElement.getAttribute("id"); 146 if (id != null && id.length() > 0) { 147 daoContext.setId(id); 148 } 149 150 NodeList children = contextElement.getChildNodes(); 151 for (int i = 0; i < children.getLength(); i++) { 152 Node child = children.item(i); 153 if (child.getNodeType() == Node.ELEMENT_NODE) { 154 if (TRANS_MGR_ELEMENT.equals(child.getNodeName())) { 155 DaoTransactionManager txMgr = parseTransactionManager((Element) child); 156 daoContext.setTransactionManager(txMgr); 157 } else if (DAO_ELEMENT.equals(child.getNodeName())) { 158 DaoImpl daoImpl = parseDao((Element) child, daoManager, daoContext); 159 daoContext.addDao(daoImpl); 160 } 161 } 162 } 163 164 return daoContext; 165 } 166 167 private DaoTransactionManager parseTransactionManager(Element transPoolElement) 168 throws DaoException { 169 DaoTransactionManager txMgr = null; 170 171 Properties attributes = parseAttributes(transPoolElement); 172 173 String implementation = attributes.getProperty("type"); 174 implementation = resolveAlias(implementation); 175 176 177 try { 178 txMgr = (DaoTransactionManager) Class.forName(implementation).newInstance(); 179 } catch (Exception e) { 180 throw new DaoException("Error while configuring DaoManager. Cause: " + e.toString(), e); 181 } 182 183 Properties props = properties; 184 185 if (props == null) { 186 props = parsePropertyElements(transPoolElement); 187 } else { 188 props.putAll(parsePropertyElements(transPoolElement)); 189 } 190 191 txMgr.configure(props); 192 193 if (txMgr == null) { 194 throw new DaoException("Error while configuring DaoManager. Some unknown condition caused the " + 195 "DAO Transaction Manager to be null after configuration."); 196 } 197 198 return txMgr; 199 } 200 201 private DaoImpl parseDao(Element element, StandardDaoManager daoManager, DaoContext daoContext) { 202 DaoImpl daoImpl = new DaoImpl(); 203 if (element.getNodeType() == Node.ELEMENT_NODE) { 204 if (DAO_ELEMENT.equals(element.getNodeName())) { 205 206 Properties attributes = parseAttributes(element); 207 208 try { 209 String iface = attributes.getProperty("interface"); 210 String impl = attributes.getProperty("implementation"); 211 daoImpl.setDaoManager(daoManager); 212 daoImpl.setDaoContext(daoContext); 213 daoImpl.setDaoInterface(Resources.classForName(iface)); 214 daoImpl.setDaoImplementation(Resources.classForName(impl)); 215 216 Class daoClass = daoImpl.getDaoImplementation(); 217 Dao dao = null; 218 219 try { 220 Constructor constructor = daoClass.getConstructor(new Class []{DaoManager.class}); 221 dao = (Dao) constructor.newInstance(new Object []{daoManager}); 222 } catch (Exception e) { 223 dao = (Dao) daoClass.newInstance(); 224 } 225 226 daoImpl.setDaoInstance(dao); 227 daoImpl.initProxy(); 228 } catch (Exception e) { 229 throw new DaoException("Error configuring DAO. Cause: " + e, e); 230 } 231 } 232 } 233 return daoImpl; 234 } 235 236 private Properties parsePropertyElements(Element propsParentElement) { 237 238 Properties props = new Properties (); 239 240 NodeList children = propsParentElement.getChildNodes(); 241 for (int i = 0; i < children.getLength(); i++) { 242 Node child = children.item(i); 243 244 if (child.getNodeType() == Node.ELEMENT_NODE) { 245 if (PROPERTY_ELEMENT.equals(child.getNodeName())) { 246 247 Properties attributes = parseAttributes(child); 248 249 String name = attributes.getProperty("name"); 250 String value = attributes.getProperty("value"); 251 252 props.setProperty(name, value); 253 } 254 } 255 256 } 257 258 return props; 259 } 260 261 private Properties parseAttributes(Node n) { 262 Properties attributes = new Properties (); 263 NamedNodeMap attributeNodes = n.getAttributes(); 264 for (int i = 0; i < attributeNodes.getLength(); i++) { 265 Node attribute = attributeNodes.item(i); 266 String value = parsePropertyTokens(attribute.getNodeValue()); 267 attributes.put(attribute.getNodeName(), value); 268 } 269 return attributes; 270 } 271 272 private String parsePropertyTokens(String string) { 273 final String OPEN = "${"; 274 final String CLOSE = "}"; 275 String newString = string; 276 if (newString != null && properties != null) { 277 int start = newString.indexOf(OPEN); 278 int end = newString.indexOf(CLOSE); 279 280 while (start > -1 && end > start) { 281 String prepend = newString.substring(0, start); 282 String append = newString.substring(end + CLOSE.length()); 283 String propName = newString.substring(start + OPEN.length(), end); 284 String propValue = properties.getProperty(propName); 285 if (propValue == null) { 286 newString = prepend + append; 287 } else { 288 newString = prepend + propValue + append; 289 } 290 start = newString.indexOf(OPEN); 291 end = newString.indexOf(CLOSE); 292 } 293 } 294 return newString; 295 } 296 297 private Document getDoc(Reader reader) { 298 try { 299 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 301 dbf.setNamespaceAware(false); 302 dbf.setValidating(true); 303 dbf.setIgnoringComments(true); 304 dbf.setIgnoringElementContentWhitespace(true); 305 dbf.setCoalescing(false); 306 dbf.setExpandEntityReferences(false); 307 308 OutputStreamWriter errorWriter = new OutputStreamWriter (System.err); 309 310 DocumentBuilder db = dbf.newDocumentBuilder(); 311 db.setErrorHandler(new SimpleErrorHandler(new PrintWriter (errorWriter, true))); 312 db.setEntityResolver(new DaoClasspathEntityResolver()); 313 314 Document doc = db.parse(new ReaderInputStream(reader)); 316 return doc; 317 } catch (Exception e) { 318 throw new NestedRuntimeException("XML Parser Error. Cause: " + e); 319 } 320 } 321 322 private String resolveAlias(String string) { 323 String newString = null; 324 if (typeAliases.containsKey(string)) { 325 newString = (String ) typeAliases.get(string); 326 } 327 if (newString != null) { 328 string = newString; 329 } 330 return string; 331 } 332 333 338 339 private static class SimpleErrorHandler implements ErrorHandler { 341 344 private PrintWriter out; 345 346 SimpleErrorHandler(PrintWriter out) { 347 this.out = out; 348 } 349 350 353 private String getParseExceptionInfo(SAXParseException spe) { 354 String systemId = spe.getSystemId(); 355 if (systemId == null) { 356 systemId = "null"; 357 } 358 String info = "URI=" + systemId + 359 " Line=" + spe.getLineNumber() + 360 ": " + spe.getMessage(); 361 return info; 362 } 363 364 367 public void warning(SAXParseException spe) throws SAXException { 368 out.println("Warning: " + getParseExceptionInfo(spe)); 369 } 370 371 public void error(SAXParseException spe) throws SAXException { 372 String message = "Error: " + getParseExceptionInfo(spe); 373 throw new SAXException (message); 374 } 375 376 public void fatalError(SAXParseException spe) throws SAXException { 377 String message = "Fatal Error: " + getParseExceptionInfo(spe); 378 throw new SAXException (message); 379 } 380 } 381 382 } 383 | Popular Tags |