Coverage report

  %line %branch
org.apache.torque.engine.database.transform.XmlToAppData$ParseStackElement
0% 
0% 

 1  
 package org.apache.torque.engine.database.transform;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 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  
 /**
 46  
  * A Class that is used to parse an input xml schema file and creates a Database
 47  
  * java structure.
 48  
  *
 49  
  * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
 50  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 51  
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
 52  
  * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
 53  
  * @author <a href="mailto:fischer@seitenbau.de">Thomas Fischer</a>
 54  
  * @version $Id: XmlToAppData.java 239626 2005-08-24 12:19:51Z henning $
 55  
  */
 56  
 public class XmlToAppData extends DefaultHandler
 57  
 {
 58  
     /** Logging class from commons.logging */
 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  
     /** remember all files we have already parsed to detect looping. */
 77  
     private Vector alreadyReadFiles;
 78  
 
 79  
     /** this is the stack to store parsing data */
 80  
     private Stack parsingStack = new Stack();
 81  
 
 82  
     static
 83  
     {
 84  
         saxFactory = SAXParserFactory.newInstance();
 85  
         saxFactory.setValidating(true);
 86  
     }
 87  
 
 88  
     /**
 89  
      * Creates a new instance for the specified database type.
 90  
      *
 91  
      * @param databaseType The type of database for the application.
 92  
      */
 93  
     public XmlToAppData(String databaseType)
 94  
     {
 95  
         database = new Database(databaseType);
 96  
         firstPass = true;
 97  
     }
 98  
 
 99  
     /**
 100  
      * Creates a new instance for the specified database type.
 101  
      *
 102  
      * @param databaseType The type of database for the application.
 103  
      * @param defaultPackage the default java package used for the om
 104  
      */
 105  
     public XmlToAppData(String databaseType, String defaultPackage)
 106  
     {
 107  
         database = new Database(databaseType);
 108  
         this.defaultPackage = defaultPackage;
 109  
         firstPass = true;
 110  
     }
 111  
 
 112  
     /**
 113  
      * Parses a XML input file and returns a newly created and
 114  
      * populated Database structure.
 115  
      *
 116  
      * @param xmlFile The input file to parse.
 117  
      * @return Database populated by <code>xmlFile</code>.
 118  
      */
 119  
     public Database parseFile(String xmlFile)
 120  
             throws EngineException
 121  
     {
 122  
         try
 123  
         {
 124  
             // in case I am missing something, make it obvious
 125  
             if (!firstPass)
 126  
             {
 127  
                 throw new Error("No more double pass");
 128  
             }
 129  
             // check to see if we alread have parsed the file
 130  
             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  
             // remember the file to avoid looping
 141  
             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  
     /**
 183  
      * EntityResolver implementation. Called by the XML parser
 184  
      *
 185  
      * @param publicId The public identifier of the external entity
 186  
      * @param systemId The system identifier of the external entity
 187  
      * @return an InputSource for the database.dtd file
 188  
      * @see DTDResolver#resolveEntity(String, String)
 189  
      */
 190  
     public InputSource resolveEntity(String class="keyword">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  
     /**
 204  
      * Handles opening elements of the xml file.
 205  
      *
 206  
      * @param uri
 207  
      * @param localName The local name (without prefix), or the empty string if
 208  
      *         Namespace processing is not being performed.
 209  
      * @param rawName The qualified name (with prefix), or the empty string if
 210  
      *         qualified names are not available.
 211  
      * @param attributes The specified or defaulted attributes
 212  
      */
 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  
                 // put current state onto the stack
 248  
                 ParseStackElement.pushState(this);
 249  
 
 250  
                 isExternalSchema = true;
 251  
 
 252  
                 parseFile(xmlFile);
 253  
                 // get the last state from the stack
 254  
                 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  
     /**
 315  
      * Handles closing elements of the xml file.
 316  
      *
 317  
      * @param uri
 318  
      * @param localName The local name (without prefix), or the empty string if
 319  
      *         Namespace processing is not being performed.
 320  
      * @param rawName The qualified name (with prefix), or the empty string if
 321  
      *         qualified names are not available.
 322  
      */
 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  
     /**
 333  
      * Handles exception which occur when the xml file is parsed
 334  
      * @param e the exception which occured while parsing
 335  
      * @throws SAXException always
 336  
      */
 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  
     /**
 352  
      * When parsing multiple files that use nested <external-schema> tags we
 353  
      * need to use a stack to remember some values.
 354  
      */
 355  
     private static class ParseStackElement
 356  
     {
 357  
         private boolean isExternalSchema;
 358  
         private String currentPackage;
 359  
         private String currentXmlFile;
 360  
         private boolean firstPass;
 361  
 
 362  
         /**
 363  
          *
 364  
          * @param parser
 365  
          */
 366  
         public ParseStackElement(XmlToAppData parser)
 367  0
         {
 368  
             // remember current state of parent object
 369  0
             isExternalSchema = parser.isExternalSchema;
 370  0
             currentPackage = parser.currentPackage;
 371  0
             currentXmlFile = parser.currentXmlFile;
 372  0
             firstPass = parser.firstPass;
 373  
 
 374  
             // push the state onto the stack
 375  0
             parser.parsingStack.push(this);
 376  0
         }
 377  
 
 378  
         /**
 379  
          * Removes the top element from the stack and activates the stored state
 380  
          *
 381  
          * @param parser
 382  
          */
 383  
         public static void popState(XmlToAppData parser)
 384  
         {
 385  0
             if (!parser.parsingStack.isEmpty())
 386  
             {
 387  0
                 ParseStackElement elem = (ParseStackElement)
 388  
                         parser.parsingStack.pop();
 389  
 
 390  
                 // activate stored state
 391  0
                 parser.isExternalSchema = elem.isExternalSchema;
 392  0
                 parser.currentPackage = elem.currentPackage;
 393  0
                 parser.currentXmlFile = elem.currentXmlFile;
 394  0
                 parser.firstPass = elem.firstPass;
 395  
             }
 396  0
         }
 397  
 
 398  
         /**
 399  
          * Stores the current state on the top of the stack.
 400  
          *
 401  
          * @param parser
 402  
          */
 403  
         public static void pushState(XmlToAppData parser)
 404  
         {
 405  0
             new ParseStackElement(parser);
 406  0
         }
 407  
     }
 408  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.