Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 381   Methods: 11
NCLOC: 193   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DescriptorHandler.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 
 55   
 package org.apache.tools.ant.taskdefs.optional.ejb;
 56   
 
 57   
 import java.io.File;
 58   
 import java.io.FileInputStream;
 59   
 import java.io.FileNotFoundException;
 60   
 import java.io.IOException;
 61   
 import java.io.InputStream;
 62   
 import java.net.URL;
 63   
 import java.util.Hashtable;
 64   
 import org.apache.tools.ant.Project;
 65   
 import org.apache.tools.ant.Task;
 66   
 import org.xml.sax.AttributeList;
 67   
 import org.xml.sax.InputSource;
 68   
 import org.xml.sax.SAXException;
 69   
 
 70   
 /**
 71   
  * Inner class used by EjbJar to facilitate the parsing of deployment
 72   
  * descriptors and the capture of appropriate information. Extends
 73   
  * HandlerBase so it only implements the methods needed. During parsing
 74   
  * creates a hashtable consisting of entries mapping the name it should be
 75   
  * inserted into an EJB jar as to a File representing the file on disk. This
 76   
  * list can then be accessed through the getFiles() method.
 77   
  */
 78   
 public class DescriptorHandler extends org.xml.sax.HandlerBase {
 79   
     private static final int STATE_LOOKING_EJBJAR = 1;
 80   
     private static final int STATE_IN_EJBJAR = 2;
 81   
     private static final int STATE_IN_BEANS = 3;
 82   
     private static final int STATE_IN_SESSION = 4;
 83   
     private static final int STATE_IN_ENTITY = 5;
 84   
     private static final int STATE_IN_MESSAGE = 6;
 85   
 
 86   
     private Task owningTask;
 87   
 
 88   
     private String publicId = null;
 89   
 
 90   
     /**
 91   
      * Bunch of constants used for storing entries in a hashtable, and for
 92   
      * constructing the filenames of various parts of the ejb jar.
 93   
      */
 94   
     private static final String EJB_REF               = "ejb-ref";
 95   
     private static final String EJB_LOCAL_REF         = "ejb-local-ref";
 96   
     private static final String HOME_INTERFACE        = "home";
 97   
     private static final String REMOTE_INTERFACE      = "remote";
 98   
     private static final String LOCAL_HOME_INTERFACE  = "local-home";
 99   
     private static final String LOCAL_INTERFACE       = "local";
 100   
     private static final String BEAN_CLASS            = "ejb-class";
 101   
     private static final String PK_CLASS              = "prim-key-class";
 102   
     private static final String EJB_NAME              = "ejb-name";
 103   
     private static final String EJB_JAR               = "ejb-jar";
 104   
     private static final String ENTERPRISE_BEANS      = "enterprise-beans";
 105   
     private static final String ENTITY_BEAN           = "entity";
 106   
     private static final String SESSION_BEAN          = "session";
 107   
     private static final String MESSAGE_BEAN          = "message-driven";
 108   
 
 109   
     /**
 110   
      * The state of the parsing
 111   
      */
 112   
     private int parseState = STATE_LOOKING_EJBJAR;
 113   
 
 114   
     /**
 115   
      * Instance variable used to store the name of the current element being
 116   
      * processed by the SAX parser.  Accessed by the SAX parser call-back methods
 117   
      * startElement() and endElement().
 118   
      */
 119   
     protected String currentElement = null;
 120   
 
 121   
     /**
 122   
      * The text of the current element
 123   
      */
 124   
     protected String currentText = null;
 125   
 
 126   
     /**
 127   
      * Instance variable that stores the names of the files as they will be
 128   
      * put into the jar file, mapped to File objects  Accessed by the SAX
 129   
      * parser call-back method characters().
 130   
      */
 131   
     protected Hashtable ejbFiles = null;
 132   
 
 133   
     /**
 134   
      * Instance variable that stores the value found in the &lt;ejb-name&gt; element
 135   
      */
 136   
     protected String ejbName = null;
 137   
 
 138   
     private Hashtable fileDTDs = new Hashtable();
 139   
 
 140   
     private Hashtable resourceDTDs = new Hashtable();
 141   
 
 142   
     private boolean inEJBRef = false;
 143   
 
 144   
     private Hashtable urlDTDs = new Hashtable();
 145   
 
 146   
     /**
 147   
      * The directory containing the bean classes and interfaces. This is
 148   
      * used for performing dependency file lookups.
 149   
      */
 150   
     private File srcDir;
 151   
 
 152  0
     public DescriptorHandler(Task task, File srcDir) {
 153  0
         this.owningTask = task;
 154  0
         this.srcDir = srcDir;
 155   
     }
 156   
 
 157  0
     public void registerDTD(String publicId, String location) {
 158  0
         if (location == null) {
 159  0
             return;
 160   
         }
 161   
 
 162  0
         File fileDTD = new File(location);
 163  0
         if (!fileDTD.exists()) {
 164   
             // resolve relative to project basedir
 165  0
             fileDTD = owningTask.getProject().resolveFile(location);
 166   
         }
 167   
         
 168  0
         if (fileDTD.exists()) {
 169  0
             if (publicId != null) {
 170  0
                 fileDTDs.put(publicId, fileDTD);
 171  0
                 owningTask.log("Mapped publicId " + publicId + " to file " + fileDTD, Project.MSG_VERBOSE);
 172   
             }
 173  0
             return;
 174   
         }
 175   
 
 176  0
         if (getClass().getResource(location) != null) {
 177  0
             if (publicId != null) {
 178  0
                 resourceDTDs.put(publicId, location);
 179  0
                 owningTask.log("Mapped publicId " + publicId + " to resource " + location, Project.MSG_VERBOSE);
 180   
             }
 181   
         }
 182   
 
 183  0
         try {
 184  0
             if (publicId != null) {
 185  0
                 URL urldtd = new URL(location);
 186  0
                 urlDTDs.put(publicId, urldtd);
 187   
             }
 188   
         } catch (java.net.MalformedURLException e) {
 189   
             //ignored
 190   
         }
 191   
 
 192   
     }
 193   
 
 194  0
     public InputSource resolveEntity(String publicId, String systemId)
 195   
         throws SAXException {
 196  0
         this.publicId = publicId;
 197   
 
 198  0
         File dtdFile = (File) fileDTDs.get(publicId);
 199  0
         if (dtdFile != null) {
 200  0
             try {
 201  0
                 owningTask.log("Resolved " + publicId + " to local file " + dtdFile, Project.MSG_VERBOSE);
 202  0
                 return new InputSource(new FileInputStream(dtdFile));
 203   
             } catch (FileNotFoundException ex) {
 204   
                 // ignore
 205   
             }
 206   
         }
 207   
 
 208  0
         String dtdResourceName = (String) resourceDTDs.get(publicId);
 209  0
         if (dtdResourceName != null) {
 210  0
             InputStream is = this.getClass().getResourceAsStream(dtdResourceName);
 211  0
             if (is != null) {
 212  0
                 owningTask.log("Resolved " + publicId + " to local resource " + dtdResourceName, Project.MSG_VERBOSE);
 213  0
                 return new InputSource(is);
 214   
             }
 215   
         }
 216   
 
 217  0
         URL dtdUrl = (URL) urlDTDs.get(publicId);
 218  0
         if (dtdUrl != null) {
 219  0
             try {
 220  0
                 InputStream is = dtdUrl.openStream();
 221  0
                 owningTask.log("Resolved " + publicId + " to url " + dtdUrl, Project.MSG_VERBOSE);
 222  0
                 return new InputSource(is);
 223   
             } catch (IOException ioe) {
 224   
                 //ignore
 225   
             }
 226   
         }
 227   
 
 228  0
         owningTask.log("Could not resolve ( publicId: " + publicId + ", systemId: " + systemId + ") to a local entity",
 229   
                         Project.MSG_INFO);
 230   
 
 231  0
         return null;
 232   
     }
 233   
 
 234   
     /**
 235   
      * Getter method that returns the set of files to include in the EJB jar.
 236   
      */
 237  0
     public Hashtable getFiles() {
 238  0
         return (ejbFiles == null) ? new Hashtable() : ejbFiles;
 239   
     }
 240   
 
 241   
     /**
 242   
      * Get the publicId of the DTD
 243   
      */
 244  0
     public String getPublicId() {
 245  0
         return publicId;
 246   
     }
 247   
 
 248   
      /**
 249   
      * Getter method that returns the value of the &lt;ejb-name&gt; element.
 250   
      */
 251  0
     public String getEjbName() {
 252  0
         return ejbName;
 253   
     }
 254   
 
 255   
     /**
 256   
      * SAX parser call-back method that is used to initialize the values of some
 257   
      * instance variables to ensure safe operation.
 258   
      */
 259  0
     public void startDocument() throws SAXException {
 260  0
         this.ejbFiles = new Hashtable(10, 1);
 261  0
         this.currentElement = null;
 262  0
         inEJBRef = false;
 263   
     }
 264   
 
 265   
 
 266   
     /**
 267   
      * SAX parser call-back method that is invoked when a new element is entered
 268   
      * into.  Used to store the context (attribute name) in the currentAttribute
 269   
      * instance variable.
 270   
      * @param name The name of the element being entered.
 271   
      * @param attrs Attributes associated to the element.
 272   
      */
 273  0
     public void startElement(String name, AttributeList attrs)
 274   
         throws SAXException {
 275  0
         this.currentElement = name;
 276  0
         currentText = "";
 277  0
         if (name.equals(EJB_REF) || name.equals(EJB_LOCAL_REF)) {
 278  0
             inEJBRef = true;
 279  0
         } else if (parseState == STATE_LOOKING_EJBJAR && name.equals(EJB_JAR)) {
 280  0
             parseState = STATE_IN_EJBJAR;
 281  0
         } else if (parseState == STATE_IN_EJBJAR && name.equals(ENTERPRISE_BEANS)) {
 282  0
             parseState = STATE_IN_BEANS;
 283  0
         } else if (parseState == STATE_IN_BEANS && name.equals(SESSION_BEAN)) {
 284  0
             parseState = STATE_IN_SESSION;
 285  0
         } else if (parseState == STATE_IN_BEANS && name.equals(ENTITY_BEAN)) {
 286  0
             parseState = STATE_IN_ENTITY;
 287  0
         } else if (parseState == STATE_IN_BEANS && name.equals(MESSAGE_BEAN)) {
 288  0
             parseState = STATE_IN_MESSAGE;
 289   
         }
 290   
     }
 291   
 
 292   
 
 293   
     /**
 294   
      * SAX parser call-back method that is invoked when an element is exited.
 295   
      * Used to blank out (set to the empty string, not nullify) the name of
 296   
      * the currentAttribute.  A better method would be to use a stack as an
 297   
      * instance variable, however since we are only interested in leaf-node
 298   
      * data this is a simpler and workable solution.
 299   
      * @param name The name of the attribute being exited. Ignored
 300   
      *        in this implementation.
 301   
      */
 302  0
     public void endElement(String name) throws SAXException {
 303  0
         processElement();
 304  0
         currentText = "";
 305  0
         this.currentElement = "";
 306  0
         if (name.equals(EJB_REF) || name.equals(EJB_LOCAL_REF)) {
 307  0
             inEJBRef = false;
 308  0
         } else if (parseState == STATE_IN_ENTITY && name.equals(ENTITY_BEAN)) {
 309  0
             parseState = STATE_IN_BEANS;
 310  0
         } else if (parseState == STATE_IN_SESSION && name.equals(SESSION_BEAN)) {
 311  0
             parseState = STATE_IN_BEANS;
 312  0
         } else if (parseState == STATE_IN_MESSAGE && name.equals(MESSAGE_BEAN)) {
 313  0
             parseState = STATE_IN_BEANS;
 314  0
         } else if (parseState == STATE_IN_BEANS && name.equals(ENTERPRISE_BEANS)) {
 315  0
             parseState = STATE_IN_EJBJAR;
 316  0
         } else if (parseState == STATE_IN_EJBJAR && name.equals(EJB_JAR)) {
 317  0
             parseState = STATE_LOOKING_EJBJAR;
 318   
         }
 319   
     }
 320   
 
 321   
     /**
 322   
      * SAX parser call-back method invoked whenever characters are located within
 323   
      * an element.  currentAttribute (modified by startElement and endElement)
 324   
      * tells us whether we are in an interesting element (one of the up to four
 325   
      * classes of an EJB).  If so then converts the classname from the format
 326   
      * org.apache.tools.ant.Parser to the convention for storing such a class,
 327   
      * org/apache/tools/ant/Parser.class.  This is then resolved into a file
 328   
      * object under the srcdir which is stored in a Hashtable.
 329   
      * @param ch A character array containing all the characters in
 330   
      *        the element, and maybe others that should be ignored.
 331   
      * @param start An integer marking the position in the char
 332   
      *        array to start reading from.
 333   
      * @param length An integer representing an offset into the
 334   
      *        char array where the current data terminates.
 335   
      */
 336  0
     public void characters(char[] ch, int start, int length)
 337   
         throws SAXException {
 338   
 
 339  0
         currentText += new String(ch, start, length);
 340   
     }
 341   
 
 342   
 
 343  0
     protected void processElement() {
 344  0
         if (inEJBRef || 
 345   
             (parseState != STATE_IN_ENTITY && parseState != STATE_IN_SESSION && parseState != STATE_IN_MESSAGE)) {
 346  0
             return;
 347   
         }
 348   
 
 349  0
         if (currentElement.equals(HOME_INTERFACE)   ||
 350   
             currentElement.equals(REMOTE_INTERFACE) ||
 351   
             currentElement.equals(LOCAL_INTERFACE) ||
 352   
             currentElement.equals(LOCAL_HOME_INTERFACE) ||
 353   
             currentElement.equals(BEAN_CLASS)       ||
 354   
             currentElement.equals(PK_CLASS)) {
 355   
 
 356   
             // Get the filename into a String object
 357  0
             File classFile = null;
 358  0
             String className = currentText.trim();
 359   
 
 360   
             // If it's a primitive wrapper then we shouldn't try and put
 361   
             // it into the jar, so ignore it.
 362  0
             if (!className.startsWith("java.") &&
 363   
                 !className.startsWith("javax.")) {
 364   
                 // Translate periods into path separators, add .class to the
 365   
                 // name, create the File object and add it to the Hashtable.
 366  0
                 className = className.replace('.', File.separatorChar);
 367  0
                 className += ".class";
 368  0
                 classFile = new File(srcDir, className);
 369  0
                 ejbFiles.put(className, classFile);
 370   
             }
 371   
         }
 372   
 
 373   
     // Get the value of the <ejb-name> tag.  Only the first occurence.
 374  0
         if (currentElement.equals(EJB_NAME)) {
 375  0
             if (ejbName == null) {
 376  0
                 ejbName = currentText.trim();
 377   
             }
 378   
         }
 379   
     }
 380   
 }
 381