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-2004 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.AppData;
 33  
 import org.apache.torque.engine.database.model.Column;
 34  
 import org.apache.torque.engine.database.model.Database;
 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.helpers.DefaultHandler;
 43  
 
 44  
 /**
 45  
  * A Class that is used to parse an input xml schema file and creates an AppData
 46  
  * java structure.
 47  
  *
 48  
  * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
 49  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 50  
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
 51  
  * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
 52  
  * @version $Id: XmlToAppData.java,v 1.8.2.2 2004/05/20 04:34:17 seade Exp $
 53  
  */
 54  
 public class XmlToAppData extends DefaultHandler
 55  
 {
 56  
     /** Logging class from commons.logging */
 57  
     private static Log log = LogFactory.getLog(XmlToAppData.class);
 58  
 
 59  
     private AppData app;
 60  
     private Database currDB;
 61  
     private Table currTable;
 62  
     private Column currColumn;
 63  
     private ForeignKey currFK;
 64  
     private Index currIndex;
 65  
     private Unique currUnique;
 66  
 
 67  
     private boolean firstPass;
 68  
     private boolean isExternalSchema;
 69  
     private String currentPackage;
 70  
     private String currentXmlFile;
 71  
     private String defaultPackage;
 72  
 
 73  
     private static SAXParserFactory saxFactory;
 74  
 
 75  
     /** remember all files we have already parsed to detect looping. */
 76  
     private Vector alreadyReadFiles;
 77  
 
 78  
     /** this is the stack to store parsing data */
 79  
     private Stack parsingStack = new Stack();
 80  
 
 81  
     static
 82  
     {
 83  
         saxFactory = SAXParserFactory.newInstance();
 84  
         saxFactory.setValidating(true);
 85  
     }
 86  
 
 87  
     /**
 88  
      * Creates a new instance for the specified database type.
 89  
      *
 90  
      * @param databaseType The type of database for the application.
 91  
      * @param defaultPackage the default java package used for the om
 92  
      * @param basePropsFilePath The base of the path to the properties
 93  
      * file, including trailing slash.
 94  
      */
 95  
     public XmlToAppData(String databaseType, String defaultPackage,
 96  
                         String basePropsFilePath)
 97  
     {
 98  
         app = new AppData(databaseType, basePropsFilePath);
 99  
         this.defaultPackage = defaultPackage;
 100  
         firstPass = true;
 101  
     }
 102  
 
 103  
     /**
 104  
      * Parses a XML input file and returns a newly created and
 105  
      * populated AppData structure.
 106  
      *
 107  
      * @param xmlFile The input file to parse.
 108  
      * @return AppData populated by <code>xmlFile</code>.
 109  
      */
 110  
     public AppData parseFile(String xmlFile)
 111  
             throws EngineException
 112  
     {
 113  
         try
 114  
         {
 115  
             // in case I am missing something, make it obvious
 116  
             if (!firstPass)
 117  
             {
 118  
                 throw new Error("No more double pass");
 119  
             }
 120  
             // check to see if we alread have parsed the file
 121  
             if ((alreadyReadFiles != null)
 122  
                     && alreadyReadFiles.contains(xmlFile))
 123  
             {
 124  
                 return app;
 125  
             }
 126  
             else if (alreadyReadFiles == null)
 127  
             {
 128  
                 alreadyReadFiles = new Vector(3, 1);
 129  
             }
 130  
             
 131  
             // remember the file to avoid looping
 132  
             alreadyReadFiles.add(xmlFile);
 133  
             
 134  
             currentXmlFile = xmlFile;
 135  
             
 136  
             SAXParser parser = saxFactory.newSAXParser();
 137  
             
 138  
             FileReader fr = null;
 139  
             try
 140  
             {
 141  
                 fr = new FileReader(xmlFile);
 142  
             }
 143  
             catch (FileNotFoundException fnfe)
 144  
             {
 145  
                 throw new FileNotFoundException
 146  
                     (new File(xmlFile).getAbsolutePath());
 147  
             }
 148  
             BufferedReader br = new BufferedReader(fr);
 149  
             try
 150  
             {
 151  
                 log.info("Parsing file: '" 
 152  
                         + (new File(xmlFile)).getName() + "'");
 153  
                 InputSource is = new InputSource(br);
 154  
                 parser.parse(is, this);
 155  
             }
 156  
             finally
 157  
             {
 158  
                 br.close();
 159  
             }
 160  
         }
 161  
         catch (Exception e)
 162  
         {
 163  
             throw new EngineException(e);
 164  
         }
 165  
         if (!isExternalSchema)
 166  
         {
 167  
             firstPass = false;
 168  
         }
 169  
         return app;
 170  
     }
 171  
     
 172  
     /**
 173  
      * EntityResolver implementation. Called by the XML parser
 174  
      *
 175  
      * @param publicId The public identifier of the external entity
 176  
      * @param systemId The system identifier of the external entity
 177  
      * @return an InputSource for the database.dtd file
 178  
      * @see org.apache.torque.engine.database.transform.DTDResolver#resolveEntity(String, String)
 179  
      */
 180  
     public InputSource resolveEntity(String class="keyword">publicId, String systemId)
 181  
             throws SAXException
 182  
     {
 183  
 		try 
 184  
 		{
 185  
 			return new DTDResolver().resolveEntity(publicId, systemId);
 186  
 		} 
 187  
 		catch (Exception e) 
 188  
 		{
 189  
 			throw new SAXException(e);
 190  
 		}
 191  
     }
 192  
 
 193  
 
 194  
     /**
 195  
      * Handles opening elements of the xml file.
 196  
      *
 197  
      * @param uri
 198  
      * @param localName The local name (without prefix), or the empty string if
 199  
      *         Namespace processing is not being performed.
 200  
      * @param rawName The qualified name (with prefix), or the empty string if
 201  
      *         qualified names are not available.
 202  
      * @param attributes The specified or defaulted attributes
 203  
      */
 204  
     public void startElement(String uri, String localName, String rawName,
 205  
                              Attributes attributes)
 206  
             throws SAXException
 207  
     {
 208  
         try
 209  
         {
 210  
             if (rawName.equals("database"))
 211  
             {
 212  
                 if (isExternalSchema)
 213  
                 {
 214  
                     currentPackage = attributes.getValue("package");
 215  
                     if (currentPackage == null)
 216  
                     {
 217  
                         currentPackage = defaultPackage;
 218  
                     }
 219  
                 }
 220  
                 else
 221  
                 {
 222  
                     currDB = app.addDatabase(attributes);
 223  
                     if (currDB.getPackage() == null)
 224  
                     {
 225  
                         currDB.setPackage(defaultPackage);
 226  
                     }
 227  
                 }
 228  
             }
 229  
             else if (rawName.equals("external-schema"))
 230  
             {
 231  
                 String xmlFile = attributes.getValue("filename");
 232  
                 if (xmlFile.charAt(0) != '/')
 233  
                 {
 234  
                     File f = new File(currentXmlFile);
 235  
                     xmlFile = new File(f.getParent(), xmlFile).getPath();
 236  
                 }
 237  
 
 238  
                 // put current state onto the stack
 239  
                 ParseStackElement.pushState(this);
 240  
 
 241  
                 isExternalSchema = true;
 242  
 
 243  
                 parseFile(xmlFile);
 244  
                 // get the last state from the stack
 245  
                 ParseStackElement.popState(this);
 246  
             }
 247  
             else if (rawName.equals("table"))
 248  
             {
 249  
                 currTable = currDB.addTable(attributes);
 250  
                 if (isExternalSchema)
 251  
                 {
 252  
                     currTable.setForReferenceOnly(true);
 253  
                     currTable.setPackage(currentPackage);
 254  
                 }
 255  
             }
 256  
             else if (rawName.equals("column"))
 257  
             {
 258  
                 currColumn = currTable.addColumn(attributes);
 259  
             }
 260  
             else if (rawName.equals("inheritance"))
 261  
             {
 262  
                 currColumn.addInheritance(attributes);
 263  
             }
 264  
             else if (rawName.equals("foreign-key"))
 265  
             {
 266  
                 currFK = currTable.addForeignKey(attributes);
 267  
             }
 268  
             else if (rawName.equals("reference"))
 269  
             {
 270  
                 currFK.addReference(attributes);
 271  
             }
 272  
             else if (rawName.equals("index"))
 273  
             {
 274  
                 currIndex = currTable.addIndex(attributes);
 275  
             }
 276  
             else if (rawName.equals("index-column"))
 277  
             {
 278  
                 currIndex.addColumn(attributes);
 279  
             }
 280  
             else if (rawName.equals("unique"))
 281  
             {
 282  
                 currUnique = currTable.addUnique(attributes);
 283  
             }
 284  
             else if (rawName.equals("unique-column"))
 285  
             {
 286  
                 currUnique.addColumn(attributes);
 287  
             }
 288  
             else if (rawName.equals("id-method-parameter"))
 289  
             {
 290  
                 currTable.addIdMethodParameter(attributes);
 291  
             }
 292  
         }
 293  
         catch (Exception e)
 294  
         {
 295  
             throw new SAXException(e);
 296  
         }
 297  
     }
 298  
 
 299  
     /**
 300  
      * Handles closing elements of the xml file.
 301  
      *
 302  
      * @param uri
 303  
      * @param localName The local name (without prefix), or the empty string if
 304  
      *         Namespace processing is not being performed.
 305  
      * @param rawName The qualified name (with prefix), or the empty string if
 306  
      *         qualified names are not available.
 307  
      */
 308  
     public void endElement(String uri, String localName, String rawName)
 309  
     {
 310  
         if (log.isDebugEnabled())
 311  
         {
 312  
             log.debug("endElement(" + uri + ", " + localName + ", "
 313  
                     + rawName + ") called");
 314  
         }
 315  
     }
 316  
 
 317  
     /**
 318  
      * When parsing multiple files that use nested <external-schema> tags we
 319  
      * need to use a stack to remember some values.
 320  
      */
 321  
     private static class ParseStackElement
 322  
     {
 323  
         private boolean isExternalSchema;
 324  
         private String currentPackage;
 325  
         private String currentXmlFile;
 326  
         private boolean firstPass;
 327  
 
 328  
         /**
 329  
          *
 330  
          * @param parser
 331  
          */
 332  
         public ParseStackElement(XmlToAppData parser)
 333  0
         {
 334  
             // remember current state of parent object
 335  0
             isExternalSchema = parser.isExternalSchema;
 336  0
             currentPackage = parser.currentPackage;
 337  0
             currentXmlFile = parser.currentXmlFile;
 338  0
             firstPass = parser.firstPass;
 339  
 
 340  
             // push the state onto the stack
 341  0
             parser.parsingStack.push(this);
 342  0
         }
 343  
 
 344  
         /**
 345  
          * Removes the top element from the stack and activates the stored state
 346  
          *
 347  
          * @param parser
 348  
          */
 349  
         public static void popState(XmlToAppData parser)
 350  
         {
 351  0
             if (!parser.parsingStack.isEmpty())
 352  
             {
 353  0
                 ParseStackElement elem = (ParseStackElement)
 354  
                         parser.parsingStack.pop();
 355  
 
 356  
                 // activate stored state
 357  0
                 parser.isExternalSchema = elem.isExternalSchema;
 358  0
                 parser.currentPackage = elem.currentPackage;
 359  0
                 parser.currentXmlFile = elem.currentXmlFile;
 360  0
                 parser.firstPass = elem.firstPass;
 361  
             }
 362  0
         }
 363  
 
 364  
         /**
 365  
          * Stores the current state on the top of the stack.
 366  
          *
 367  
          * @param parser
 368  
          */
 369  
         public static void pushState(XmlToAppData parser)
 370  
         {
 371  0
             new ParseStackElement(parser);
 372  0
         }
 373  
     }
 374  
 }

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