View Javadoc

1   package net.sf.cantina.util;
2   import org.apache.log4j.Logger;
3   import org.xml.sax.InputSource;
4   import org.xml.sax.SAXException;
5   import org.xml.sax.SAXParseException;
6   import org.xml.sax.helpers.DefaultHandler;
7   
8   import java.io.IOException;
9   import java.net.URL;
10  import java.util.ArrayList;
11  import java.util.Arrays;
12  import java.util.List;
13  
14  /***
15   * SAX Default Handler.
16   * Provided to a SAXParser as DefaultHandler,
17   * will monitor parsing exceptions and provide
18   * cached dtds (the ones that come with the dostribution,
19   * i.e. xhtml, etc.).
20   * @author Stephane JAIS
21   * 
22   */
23  
24  public class SAXDefaultHandler
25  extends DefaultHandler
26  {
27    static Logger logger = Logger.getLogger(SAXDefaultHandler.class);
28  
29    /*** The SYSTEM of the XHTML transitional dtd */
30    public static final String DTD_XHTML_TRANS = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";
31    /*** The SYSTEM of the XHTML latin1 entites */
32    public static final String ENT_XHTML_LAT1 = "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent";
33    /*** The SYSTEM of the XHTML special entites */
34    public static final String ENT_XHTML_SPECIAL = "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent";
35    /*** The SYSTEM of the XHTML symbol entites */
36    public static final String ENT_XHTML_SYMBOL = "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent";
37    /*** The SYSTEM of the Cantina Text DTD */
38    public static final String TEXT_SYSTEM = "http://www.cantinaweb.org/dtds/text.dtd";
39    /*** The PUBLIC ID of the Cantina Text DTD */
40    public static final String TEXT_PUBLIC_ID = "-//Cantina SW.//DTD Cantina Text 1.0//EN";
41    /*** The name of the text DTD */
42    public static final String TEXT_NAME = "text";
43  
44    /*** The directory used to store cached DTDs */
45    public static final String CACHE_DIR = "net/sf/cantina/resources";
46  
47    /*** All the DTDs that should be found in net.sf.cantina.resources */
48    public static final String[] CACHED_RESOURCES = {
49      DTD_XHTML_TRANS,
50      ENT_XHTML_LAT1,
51      ENT_XHTML_SPECIAL,
52      ENT_XHTML_SYMBOL,
53      TEXT_SYSTEM
54    };
55  
56    // Instance variables.
57    private List errors = new ArrayList();
58    private StringBuffer buffer = new StringBuffer();
59  
60    /***
61      * Contructs a SAXDefaultHandler that will
62      * put any SAXException in the provided List.
63      * @param c The List that should hold sax errors.
64      */
65  
66    public SAXDefaultHandler(List c)
67    {
68      errors=c;
69    } 
70  
71    /***
72      * Contructs a SAXDefaultHandler that will
73      * put any SAXException in the provided List,
74      * and append all CDATA to the privded StringBuffer
75      * @param c The List that should hold sax errors.
76      * @param s The string buffer that should contain CDATA
77      */
78  
79    public SAXDefaultHandler(List c, StringBuffer s)
80    {
81      this(c);
82      buffer=s;
83    } 
84  
85    /***
86      * This method is called by the SAX parser when CDATA is encountered.
87      */
88  
89    public void characters(char[] ch, int start, int length)
90    {
91        this.buffer.append(new String(ch, start, length));
92    } 
93  
94  
95    /*** Captures warning */
96    public void warning (SAXParseException e)
97      throws SAXException
98    {
99      logger.debug("Invalid XML (warning).",e);
100     errors.add(e);
101     throw e;
102   } 
103 
104   /*** Captures fatalErrors */
105   public void fatalError (SAXParseException e)
106     throws SAXException
107   {
108     error(e);
109   }
110 
111   /*** Captures errors */
112   public void error (SAXParseException e)
113     throws SAXException
114   {
115     logger.debug("Invalid XML (error).",e);
116     errors.add(e);
117     throw e;
118   } 
119 
120   /*** Provide an InputSource to cached DTDs */
121 	public InputSource resolveEntity (String publicId, String systemId) {
122     List cachedResources = Arrays.asList(CACHED_RESOURCES);
123     if (cachedResources.contains(systemId))
124     {
125       String filename = systemId.substring(systemId.lastIndexOf("/") + 1);
126       logger.debug("Trying to locate ["+systemId+"] as file ["+filename+"]");
127       URL resource = Loader.getResource(CACHE_DIR + "/" + filename);
128       if (resource == null)
129       {
130         logger.debug("Resource ["+systemId+"] not found in classpath");
131         return null;
132       } 
133       logger.debug("Found resource ["+resource.toString()+"]");
134       try
135       {
136         InputSource source = new InputSource(resource.openStream());
137         source.setPublicId(publicId);
138         source.setSystemId(systemId);
139         logger.debug("Returning InputSource ["+source.toString()+"]");
140         return source;
141       } catch (IOException e)
142       {
143         logger.warn("Could not open stream to URL ["+resource.toString()+"]",e);
144       } 
145     } else
146     {
147       logger.debug("Resource ["+systemId+"] is not cached, getting it from the Internet.");
148     }  
149     // Default behavior
150     return null;
151   }
152 }
153