001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.xml;
018:
019: import org.apache.avalon.framework.logger.Logger;
020:
021: import org.xml.sax.Attributes;
022: import org.xml.sax.DocumentHandler;
023: import org.xml.sax.Locator;
024: import org.xml.sax.SAXException;
025: import org.xml.sax.helpers.AttributeListImpl;
026:
027: import java.util.Vector;
028:
029: /**
030: * This class is an utility class "wrapping" around a SAX version 1.0
031: * <code>DocumentHandler</code> and forwarding it those events received throug
032: * its <code>XMLConsumers</code> interface.
033: * <br>
034: * This class fully supports XML namespaces, converting
035: * <code>startPrefixMapping(...)</code> and <code>endPrefixMapping(...)</code>
036: * calls into appropriate <code>xmlns</code> and <code>xmlns:...</code> element
037: * attributes.
038: *
039: * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
040: * (Apache Software Foundation)
041: * @version CVS $Id: DocumentHandlerWrapper.java 433543 2006-08-22 06:22:54Z crossley $
042: */
043: public class DocumentHandlerWrapper extends AbstractXMLConsumer {
044:
045: protected Logger log;
046:
047: /** The current namespaces table. */
048: private NamespacesTable namespaces = new NamespacesTable();
049: /** The vector of namespaces declarations to include in the next element. */
050: private Vector undecl = new Vector();
051:
052: /** The current <code>DocumentHandler</code>. */
053: protected DocumentHandler documentHandler = null;
054:
055: /**
056: * Create a new <code>DocumentHandlerWrapper</code> instance.
057: */
058: public DocumentHandlerWrapper() {
059: super ();
060: }
061:
062: /**
063: * Create a new <code>DocumentHandlerWrapper</code> instance.
064: */
065: public DocumentHandlerWrapper(DocumentHandler document) {
066: this ();
067: this .setDocumentHandler(document);
068: }
069:
070: /**
071: * Provide component with a logger.
072: *
073: * @param logger the logger
074: */
075: public void enableLogging(Logger logger) {
076: if (this .log == null) {
077: this .log = logger;
078: }
079: }
080:
081: /**
082: * Implementation of the recycle method
083: */
084: public void recycle() {
085: this .documentHandler = null;
086: }
087:
088: /**
089: * Set the <code>DocumentHandler</code> that will receive XML data.
090: *
091: * @exception IllegalStateException If the <code>DocumentHandler</code>
092: * was already set.
093: */
094: public void setDocumentHandler(DocumentHandler document)
095: throws IllegalStateException {
096: if (this .documentHandler != null)
097: throw new IllegalStateException();
098: this .documentHandler = document;
099: }
100:
101: /**
102: * Receive an object for locating the origin of SAX document events.
103: */
104: public void setDocumentLocator(Locator locator) {
105: if (this .documentHandler == null)
106: return;
107: else
108: this .documentHandler.setDocumentLocator(locator);
109: }
110:
111: /**
112: * Receive notification of the beginning of a document.
113: */
114: public void startDocument() throws SAXException {
115: if (this .documentHandler == null)
116: throw new SAXException("DocumentHandler not set");
117: this .documentHandler.startDocument();
118: }
119:
120: /**
121: * Receive notification of the end of a document.
122: */
123: public void endDocument() throws SAXException {
124: if (this .documentHandler == null)
125: throw new SAXException("DocumentHandler not set");
126: this .documentHandler.endDocument();
127: }
128:
129: /**
130: * Begin the scope of a prefix-URI Namespace mapping.
131: */
132: public void startPrefixMapping(String prefix, String uri)
133: throws SAXException {
134: this .undecl.addElement(this .namespaces.addDeclaration(prefix,
135: uri));
136: }
137:
138: /**
139: * End the scope of a prefix-URI mapping.
140: */
141: public void endPrefixMapping(String prefix) throws SAXException {
142: if (namespaces.removeDeclaration(prefix) == null)
143: throw new SAXException("Namespace prefix \"" + prefix
144: + "\" never declared");
145: }
146:
147: /**
148: * Receive notification of the beginning of an element.
149: */
150: public void startElement(String uri, String loc, String raw,
151: Attributes a) throws SAXException {
152: if (this .documentHandler == null)
153: throw new SAXException("DocumentHandler not set");
154: NamespacesTable.Name name = this .namespaces.resolve(uri, raw,
155: null, loc);
156: // Create the AttributeList
157: AttributeListImpl a2 = new AttributeListImpl();
158: // Set the xmlns:...="..." attributes
159: if (this .undecl.size() > 0) {
160: for (int x = 0; x < this .undecl.size(); x++) {
161: NamespacesTable.Declaration dec = null;
162: dec = (NamespacesTable.Declaration) this .undecl
163: .elementAt(x);
164: String aname = "xmlns";
165: if (dec.getPrefix().length() > 0)
166: aname = "xmlns:" + dec.getPrefix();
167: a2.addAttribute(aname, "CDATA", dec.getUri());
168: }
169: this .undecl.clear();
170: }
171: // Set the real attributes
172: for (int x = 0; x < a.getLength(); x++) {
173: NamespacesTable.Name aname = namespaces
174: .resolve(a.getURI(x), a.getQName(x), null, a
175: .getLocalName(x));
176: a2.addAttribute(aname.getQName(), a.getType(x), a
177: .getValue(x));
178: }
179: // Call the document handler startElement() method.
180: this .documentHandler.startElement(name.getQName(), a2);
181: }
182:
183: /**
184: * Receive notification of the end of an element.
185: */
186: public void endElement(String uri, String loc, String raw)
187: throws SAXException {
188: if (this .documentHandler == null)
189: throw new SAXException("DocumentHandler not set");
190: NamespacesTable.Name name = this .namespaces.resolve(uri, raw,
191: null, loc);
192: this .documentHandler.endElement(name.getQName());
193: }
194:
195: /**
196: * Receive notification of character data.
197: */
198: public void characters(char ch[], int start, int len)
199: throws SAXException {
200: if (this .documentHandler == null)
201: throw new SAXException("DocumentHandler not set");
202: this .documentHandler.characters(ch, start, len);
203: }
204:
205: /**
206: * Receive notification of ignorable whitespace in element content.
207: */
208: public void ignorableWhitespace(char ch[], int start, int len)
209: throws SAXException {
210: if (this .documentHandler == null)
211: throw new SAXException("DocumentHandler not set");
212: this .documentHandler.ignorableWhitespace(ch, start, len);
213: }
214:
215: /**
216: * Receive notification of a processing instruction.
217: */
218: public void processingInstruction(String target, String data)
219: throws SAXException {
220: if (this .documentHandler == null)
221: throw new SAXException("DocumentHandler not set");
222: this.documentHandler.processingInstruction(target, data);
223: }
224: }
|