View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 1999-2002 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  
36  package org.exolab.castor.xml.schema.reader;
37  
38  import org.exolab.castor.xml.AttributeSet;
39  import org.exolab.castor.xml.NamespacesStack;
40  import org.exolab.castor.xml.XMLException;
41  import org.exolab.castor.xml.util.AttributeSetImpl;
42  import org.xml.sax.AttributeList;
43  import org.xml.sax.DocumentHandler;
44  import org.xml.sax.Locator;
45  import org.xml.sax.SAXException;
46  import org.xml.sax.SAXParseException;
47  
48  /**
49   * A SAX adapter class for the ComponentReader.
50   * 
51   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
52   * @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $
53   **/
54  @SuppressWarnings("deprecation")
55  public final class Sax2ComponentReader implements DocumentHandler, org.xml.sax.ErrorHandler {
56  
57    private static final String XMLNS = "xmlns";
58    private static final String XMLNS_PREFIX = XMLNS + ":";
59    private static final String XML_PREFIX = "xml";
60  
61    private ComponentReader componentReader = null;
62  
63    /**
64     * Represents the namespaces stack.
65     */
66    private NamespacesStack namespacesStack = null;
67  
68    public Sax2ComponentReader(ComponentReader compReader) {
69      super();
70      componentReader = compReader;
71      namespacesStack = new NamespacesStack();
72    }
73  
74    /**
75     * Processes the attributes and namespace declarations found in the given SAX AttributeList. The
76     * global AttributeSet is cleared and updated with the attributes. Namespace declarations are
77     * added to the set of namespaces in scope.
78     * 
79     * @param atts the AttributeList to process.
80     **/
81    private AttributeSet processAttributeList(AttributeList atts) throws SAXException {
82  
83      if (atts == null)
84        return new AttributeSetImpl(0);
85  
86      // -- process all namespaces first
87      int attCount = 0;
88      boolean[] validAtts = new boolean[atts.getLength()];
89      for (int i = 0; i < validAtts.length; i++) {
90        String attName = atts.getName(i);
91        if (attName.equals(XMLNS)) {
92          namespacesStack.addNamespace("", atts.getValue(i));
93        } else if (attName.startsWith(XMLNS_PREFIX)) {
94          String prefix = attName.substring(XMLNS_PREFIX.length());
95          namespacesStack.addNamespace(prefix, atts.getValue(i));
96        } else {
97          validAtts[i] = true;
98          ++attCount;
99        }
100     }
101     // -- process validAtts...if any exist
102     AttributeSetImpl attSet = null;
103     if (attCount > 0) {
104       attSet = new AttributeSetImpl(attCount);
105       for (int i = 0; i < validAtts.length; i++) {
106         if (!validAtts[i])
107           continue;
108         String namespace = null;
109         String attName = atts.getName(i);
110         int idx = attName.indexOf(':');
111         if (idx > 0) {
112           String prefix = attName.substring(0, idx);
113           if (!prefix.equals(XML_PREFIX)) {
114             attName = attName.substring(idx + 1);
115             namespace = namespacesStack.getNamespaceURI(prefix);
116             if (namespace == null) {
117               String error = "The namespace associated with " + "the prefix '" + prefix
118                   + "' could not be resolved.";
119               throw new SAXException(error);
120 
121             }
122           }
123         }
124         attSet.setAttribute(attName, atts.getValue(i), namespace);
125       }
126     } else
127       attSet = new AttributeSetImpl(0);
128 
129     return attSet;
130 
131   }
132 
133   public void characters(char[] ch, int start, int length) throws org.xml.sax.SAXException {
134     try {
135       componentReader.characters(ch, start, length);
136     } catch (XMLException ex) {
137       throw new SAXException(ex);
138     }
139 
140   }
141 
142   public void endDocument() throws org.xml.sax.SAXException {
143     // -- do nothing
144   }
145 
146   public void endElement(String name) throws org.xml.sax.SAXException {
147     String namespace = null;
148     int idx = name.indexOf(':');
149     if (idx >= 0) {
150       String prefix = name.substring(0, idx);
151       name = name.substring(idx + 1);
152       namespace = namespacesStack.getNamespaceURI(prefix);
153     } else
154       namespace = namespacesStack.getDefaultNamespaceURI();
155 
156     // remove namespaces
157     namespacesStack.removeNamespaceScope();
158 
159     try {
160       componentReader.endElement(name, namespace);
161     } catch (XMLException ex) {
162       throw new SAXException(ex);
163     }
164   }
165 
166   public void ignorableWhitespace(char[] ch, int start, int length)
167       throws org.xml.sax.SAXException {
168     // -- do nothing
169   }
170 
171   public void processingInstruction(String target, String data) throws org.xml.sax.SAXException {
172     // -- do nothing
173   }
174 
175   public void setDocumentLocator(Locator locator) {
176     componentReader.setDocumentLocator(locator);
177   }
178 
179   public void startDocument() throws org.xml.sax.SAXException {
180     // -- do nothing
181   }
182 
183   public void startElement(String name, AttributeList atts) throws org.xml.sax.SAXException {
184     // -- create new Namespace scope
185     namespacesStack.addNewNamespaceScope();
186 
187     // -- handle namespaces
188     AttributeSet attSet = processAttributeList(atts);
189 
190     String namespace = null;
191     int idx = name.indexOf(':');
192     if (idx >= 0) {
193       String prefix = name.substring(0, idx);
194       name = name.substring(idx + 1);
195       namespace = namespacesStack.getNamespaceURI(prefix);
196     } else {
197       namespace = namespacesStack.getNamespaceURI("");
198     }
199 
200     try {
201       componentReader.startElement(name, namespace, attSet,
202           namespacesStack.getCurrentNamespaceScope());
203     } catch (XMLException ex) {
204       throw new SAXException(ex);
205     }
206   }
207 
208   public void error(SAXParseException exception) throws org.xml.sax.SAXException {
209     String systemId = exception.getSystemId();
210     String err = "Parsing Error : " + exception.getMessage() + '\n' + "Line : "
211         + exception.getLineNumber() + '\n' + "Column : " + exception.getColumnNumber() + '\n';
212     if (systemId != null) {
213       err = "In document: '" + systemId + "'\n" + err;
214     }
215 
216     throw new SAXException(err);
217   }
218 
219   public void fatalError(SAXParseException exception) throws org.xml.sax.SAXException {
220     String systemId = exception.getSystemId();
221     String err = "Parsing Error : " + exception.getMessage() + '\n' + "Line : "
222         + exception.getLineNumber() + '\n' + "Column : " + exception.getColumnNumber() + '\n';
223     if (systemId != null) {
224       err = "In document: '" + systemId + "'\n" + err;
225     }
226     throw new SAXException(err);
227   }
228 
229   public void warning(SAXParseException exception) throws org.xml.sax.SAXException {
230     String systemId = exception.getSystemId();
231     String err = "Parsing Error : " + exception.getMessage() + '\n' + "Line : "
232         + exception.getLineNumber() + '\n' + "Column : " + exception.getColumnNumber() + '\n';
233     if (systemId != null) {
234       err = "In document: '" + systemId + "'\n" + err;
235     }
236     throw new SAXException(err);
237   }
238 
239 }