1 package org.apache.torque.engine.database.transform; 2 3 18 19 import java.io.BufferedReader ; 20 import java.io.File ; 21 import java.io.FileNotFoundException ; 22 import java.io.FileReader ; 23 import java.util.Stack ; 24 import java.util.Vector ; 25 26 import javax.xml.parsers.SAXParser ; 27 import javax.xml.parsers.SAXParserFactory ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.apache.torque.engine.EngineException; 32 import org.apache.torque.engine.database.model.Column; 33 import org.apache.torque.engine.database.model.Database; 34 import org.apache.torque.engine.database.model.Domain; 35 import org.apache.torque.engine.database.model.ForeignKey; 36 import org.apache.torque.engine.database.model.Index; 37 import org.apache.torque.engine.database.model.Table; 38 import org.apache.torque.engine.database.model.Unique; 39 import org.xml.sax.Attributes ; 40 import org.xml.sax.InputSource ; 41 import org.xml.sax.SAXException ; 42 import org.xml.sax.SAXParseException ; 43 import org.xml.sax.helpers.DefaultHandler ; 44 45 56 public class XmlToAppData extends DefaultHandler 57 { 58 59 private static Log log = LogFactory.getLog(XmlToAppData.class); 60 61 private Database database; 62 private Table currTable; 63 private Column currColumn; 64 private ForeignKey currFK; 65 private Index currIndex; 66 private Unique currUnique; 67 68 private boolean firstPass; 69 private boolean isExternalSchema; 70 private String currentPackage; 71 private String currentXmlFile; 72 private String defaultPackage; 73 74 private static SAXParserFactory saxFactory; 75 76 77 private Vector alreadyReadFiles; 78 79 80 private Stack parsingStack = new Stack (); 81 82 static 83 { 84 saxFactory = SAXParserFactory.newInstance(); 85 saxFactory.setValidating(true); 86 } 87 88 93 public XmlToAppData(String databaseType) 94 { 95 database = new Database(databaseType); 96 firstPass = true; 97 } 98 99 105 public XmlToAppData(String databaseType, String defaultPackage) 106 { 107 database = new Database(databaseType); 108 this.defaultPackage = defaultPackage; 109 firstPass = true; 110 } 111 112 119 public Database parseFile(String xmlFile) 120 throws EngineException 121 { 122 try 123 { 124 if (!firstPass) 126 { 127 throw new Error ("No more double pass"); 128 } 129 if ((alreadyReadFiles != null) 131 && alreadyReadFiles.contains(xmlFile)) 132 { 133 return database; 134 } 135 else if (alreadyReadFiles == null) 136 { 137 alreadyReadFiles = new Vector (3, 1); 138 } 139 140 alreadyReadFiles.add(xmlFile); 142 143 currentXmlFile = xmlFile; 144 145 SAXParser parser = saxFactory.newSAXParser(); 146 147 FileReader fr = null; 148 try 149 { 150 fr = new FileReader (xmlFile); 151 } 152 catch (FileNotFoundException fnfe) 153 { 154 throw new FileNotFoundException 155 (new File (xmlFile).getAbsolutePath()); 156 } 157 BufferedReader br = new BufferedReader (fr); 158 try 159 { 160 log.info("Parsing file: '" 161 + (new File (xmlFile)).getName() + "'"); 162 InputSource is = new InputSource (br); 163 parser.parse(is, this); 164 } 165 finally 166 { 167 br.close(); 168 } 169 } 170 catch (Exception e) 171 { 172 throw new EngineException(e); 173 } 174 if (!isExternalSchema) 175 { 176 firstPass = false; 177 } 178 database.doFinalInitialization(); 179 return database; 180 } 181 182 190 public InputSource resolveEntity(String publicId, String systemId) 191 throws SAXException 192 { 193 try 194 { 195 return new DTDResolver().resolveEntity(publicId, systemId); 196 } 197 catch (Exception e) 198 { 199 throw new SAXException (e); 200 } 201 } 202 203 213 public void startElement(String uri, String localName, String rawName, 214 Attributes attributes) 215 throws SAXException 216 { 217 try 218 { 219 if (rawName.equals("database")) 220 { 221 if (isExternalSchema) 222 { 223 currentPackage = attributes.getValue("package"); 224 if (currentPackage == null) 225 { 226 currentPackage = defaultPackage; 227 } 228 } 229 else 230 { 231 database.loadFromXML(attributes); 232 if (database.getPackage() == null) 233 { 234 database.setPackage(defaultPackage); 235 } 236 } 237 } 238 else if (rawName.equals("external-schema")) 239 { 240 String xmlFile = attributes.getValue("filename"); 241 if (xmlFile.charAt(0) != '/') 242 { 243 File f = new File (currentXmlFile); 244 xmlFile = new File (f.getParent(), xmlFile).getPath(); 245 } 246 247 ParseStackElement.pushState(this); 249 250 isExternalSchema = true; 251 252 parseFile(xmlFile); 253 ParseStackElement.popState(this); 255 } 256 else if (rawName.equals("domain")) 257 { 258 Domain domain = new Domain(); 259 domain.loadFromXML(attributes, database.getPlatform()); 260 database.addDomain(domain); 261 } 262 else if (rawName.equals("table")) 263 { 264 currTable = database.addTable(attributes); 265 if (isExternalSchema) 266 { 267 currTable.setForReferenceOnly(true); 268 currTable.setPackage(currentPackage); 269 } 270 } 271 else if (rawName.equals("column")) 272 { 273 currColumn = currTable.addColumn(attributes); 274 } 275 else if (rawName.equals("inheritance")) 276 { 277 currColumn.addInheritance(attributes); 278 } 279 else if (rawName.equals("foreign-key")) 280 { 281 currFK = currTable.addForeignKey(attributes); 282 } 283 else if (rawName.equals("reference")) 284 { 285 currFK.addReference(attributes); 286 } 287 else if (rawName.equals("index")) 288 { 289 currIndex = currTable.addIndex(attributes); 290 } 291 else if (rawName.equals("index-column")) 292 { 293 currIndex.addColumn(attributes); 294 } 295 else if (rawName.equals("unique")) 296 { 297 currUnique = currTable.addUnique(attributes); 298 } 299 else if (rawName.equals("unique-column")) 300 { 301 currUnique.addColumn(attributes); 302 } 303 else if (rawName.equals("id-method-parameter")) 304 { 305 currTable.addIdMethodParameter(attributes); 306 } 307 } 308 catch (Exception e) 309 { 310 throw new SAXException (e); 311 } 312 } 313 314 323 public void endElement(String uri, String localName, String rawName) 324 { 325 if (log.isDebugEnabled()) 326 { 327 log.debug("endElement(" + uri + ", " + localName + ", " 328 + rawName + ") called"); 329 } 330 } 331 332 337 public void error(SAXParseException e) throws SAXException 338 { 339 log.error("Sax parser threw an Exception", e); 340 throw new SAXException ( 341 "Error while parsing " 342 + currentXmlFile 343 + " at line " 344 + e.getLineNumber() 345 + " column " 346 + e.getColumnNumber() 347 + " : " 348 + e.getMessage()); 349 } 350 351 355 private static class ParseStackElement 356 { 357 private boolean isExternalSchema; 358 private String currentPackage; 359 private String currentXmlFile; 360 private boolean firstPass; 361 362 366 public ParseStackElement(XmlToAppData parser) 367 { 368 isExternalSchema = parser.isExternalSchema; 370 currentPackage = parser.currentPackage; 371 currentXmlFile = parser.currentXmlFile; 372 firstPass = parser.firstPass; 373 374 parser.parsingStack.push(this); 376 } 377 378 383 public static void popState(XmlToAppData parser) 384 { 385 if (!parser.parsingStack.isEmpty()) 386 { 387 ParseStackElement elem = (ParseStackElement) 388 parser.parsingStack.pop(); 389 390 parser.isExternalSchema = elem.isExternalSchema; 392 parser.currentPackage = elem.currentPackage; 393 parser.currentXmlFile = elem.currentXmlFile; 394 parser.firstPass = elem.firstPass; 395 } 396 } 397 398 403 public static void pushState(XmlToAppData parser) 404 { 405 new ParseStackElement(parser); 406 } 407 } 408 } 409 | Popular Tags |