001: /*
002: * Copyright 2002-2008 Andy Clark
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.cyberneko.html.filters;
018:
019: import java.lang.reflect.InvocationTargetException;
020: import java.lang.reflect.Method;
021:
022: import org.cyberneko.html.HTMLComponent;
023:
024: import org.apache.xerces.xni.Augmentations;
025: import org.apache.xerces.xni.NamespaceContext;
026: import org.apache.xerces.xni.QName;
027: import org.apache.xerces.xni.XMLAttributes;
028: import org.apache.xerces.xni.XMLDocumentHandler;
029: import org.apache.xerces.xni.XMLLocator;
030: import org.apache.xerces.xni.XMLResourceIdentifier;
031: import org.apache.xerces.xni.XMLString;
032: import org.apache.xerces.xni.XNIException;
033: import org.apache.xerces.xni.parser.XMLComponentManager;
034: import org.apache.xerces.xni.parser.XMLConfigurationException;
035: import org.apache.xerces.xni.parser.XMLDocumentFilter;
036: import org.apache.xerces.xni.parser.XMLDocumentSource;
037:
038: /**
039: * This class implements a filter that simply passes document
040: * events to the next handler. It can be used as a base class to
041: * simplify the development of new document filters.
042: *
043: * @author Andy Clark
044: *
045: * @version $Id: DefaultFilter.java,v 1.7 2005/02/14 03:56:54 andyc Exp $
046: */
047: public class DefaultFilter implements XMLDocumentFilter, HTMLComponent {
048:
049: //
050: // Data
051: //
052:
053: /** Document handler. */
054: protected XMLDocumentHandler fDocumentHandler;
055:
056: /** Document source. */
057: protected XMLDocumentSource fDocumentSource;
058:
059: //
060: // XMLDocumentSource methods
061: //
062:
063: /** Sets the document handler. */
064: public void setDocumentHandler(XMLDocumentHandler handler) {
065: fDocumentHandler = handler;
066: } // setDocumentHandler(XMLDocumentHandler)
067:
068: // @since Xerces 2.1.0
069:
070: /** Returns the document handler. */
071: public XMLDocumentHandler getDocumentHandler() {
072: return fDocumentHandler;
073: } // getDocumentHandler():XMLDocumentHandler
074:
075: /** Sets the document source. */
076: public void setDocumentSource(XMLDocumentSource source) {
077: fDocumentSource = source;
078: } // setDocumentSource(XMLDocumentSource)
079:
080: /** Returns the document source. */
081: public XMLDocumentSource getDocumentSource() {
082: return fDocumentSource;
083: } // getDocumentSource():XMLDocumentSource
084:
085: //
086: // XMLDocumentHandler methods
087: //
088:
089: // since Xerces-J 2.2.0
090:
091: /** Start document. */
092: public void startDocument(XMLLocator locator, String encoding,
093: NamespaceContext nscontext, Augmentations augs)
094: throws XNIException {
095: if (fDocumentHandler != null) {
096: try {
097: // NOTE: Hack to allow the default filter to work with
098: // old and new versions of the XNI document handler
099: // interface. -Ac
100: Class cls = fDocumentHandler.getClass();
101: Class[] types = { XMLLocator.class, String.class,
102: NamespaceContext.class, Augmentations.class };
103: Method method = cls.getMethod("startDocument", types);
104: Object[] params = { locator, encoding, nscontext, augs };
105: method.invoke(fDocumentHandler, params);
106: } catch (IllegalAccessException e) {
107: throw new XNIException(e);
108: } catch (InvocationTargetException e) {
109: throw new XNIException(e);
110: } catch (NoSuchMethodException e) {
111: try {
112: // NOTE: Hack to allow the default filter to work with
113: // old and new versions of the XNI document handler
114: // interface. -Ac
115: Class cls = fDocumentHandler.getClass();
116: Class[] types = { XMLLocator.class, String.class,
117: Augmentations.class };
118: Method method = cls.getMethod("startDocument",
119: types);
120: Object[] params = { locator, encoding, augs };
121: method.invoke(fDocumentHandler, params);
122: } catch (NoSuchMethodException ex) {
123: // NOTE: Should not happen!
124: throw new XNIException(ex);
125: } catch (IllegalAccessException ex) {
126: // NOTE: Should not happen!
127: throw new XNIException(ex);
128: } catch (InvocationTargetException ex) {
129: // NOTE: Should not happen!
130: throw new XNIException(ex);
131: }
132: }
133: }
134: } // startDocument(XMLLocator,String,Augmentations)
135:
136: // old methods
137:
138: /** XML declaration. */
139: public void xmlDecl(String version, String encoding,
140: String standalone, Augmentations augs) throws XNIException {
141: if (fDocumentHandler != null) {
142: fDocumentHandler.xmlDecl(version, encoding, standalone,
143: augs);
144: }
145: } // xmlDecl(String,String,String,Augmentations)
146:
147: /** Doctype declaration. */
148: public void doctypeDecl(String root, String publicId,
149: String systemId, Augmentations augs) throws XNIException {
150: if (fDocumentHandler != null) {
151: fDocumentHandler
152: .doctypeDecl(root, publicId, systemId, augs);
153: }
154: } // doctypeDecl(String,String,String,Augmentations)
155:
156: /** Comment. */
157: public void comment(XMLString text, Augmentations augs)
158: throws XNIException {
159: if (fDocumentHandler != null) {
160: fDocumentHandler.comment(text, augs);
161: }
162: } // comment(XMLString,Augmentations)
163:
164: /** Processing instruction. */
165: public void processingInstruction(String target, XMLString data,
166: Augmentations augs) throws XNIException {
167: if (fDocumentHandler != null) {
168: fDocumentHandler.processingInstruction(target, data, augs);
169: }
170: } // processingInstruction(String,XMLString,Augmentations)
171:
172: /** Start element. */
173: public void startElement(QName element, XMLAttributes attributes,
174: Augmentations augs) throws XNIException {
175: if (fDocumentHandler != null) {
176: fDocumentHandler.startElement(element, attributes, augs);
177: }
178: } // startElement(QName,XMLAttributes,Augmentations)
179:
180: /** Empty element. */
181: public void emptyElement(QName element, XMLAttributes attributes,
182: Augmentations augs) throws XNIException {
183: if (fDocumentHandler != null) {
184: fDocumentHandler.emptyElement(element, attributes, augs);
185: }
186: } // emptyElement(QName,XMLAttributes,Augmentations)
187:
188: /** Characters. */
189: public void characters(XMLString text, Augmentations augs)
190: throws XNIException {
191: if (fDocumentHandler != null) {
192: fDocumentHandler.characters(text, augs);
193: }
194: } // characters(XMLString,Augmentations)
195:
196: /** Ignorable whitespace. */
197: public void ignorableWhitespace(XMLString text, Augmentations augs)
198: throws XNIException {
199: if (fDocumentHandler != null) {
200: fDocumentHandler.ignorableWhitespace(text, augs);
201: }
202: } // ignorableWhitespace(XMLString,Augmentations)
203:
204: /** Start general entity. */
205: public void startGeneralEntity(String name,
206: XMLResourceIdentifier id, String encoding,
207: Augmentations augs) throws XNIException {
208: if (fDocumentHandler != null) {
209: fDocumentHandler.startGeneralEntity(name, id, encoding,
210: augs);
211: }
212: } // startGeneralEntity(String,XMLResourceIdentifier,String,Augmentations)
213:
214: /** Text declaration. */
215: public void textDecl(String version, String encoding,
216: Augmentations augs) throws XNIException {
217: if (fDocumentHandler != null) {
218: fDocumentHandler.textDecl(version, encoding, augs);
219: }
220: } // textDecl(String,String,Augmentations)
221:
222: /** End general entity. */
223: public void endGeneralEntity(String name, Augmentations augs)
224: throws XNIException {
225: if (fDocumentHandler != null) {
226: fDocumentHandler.endGeneralEntity(name, augs);
227: }
228: } // endGeneralEntity(String,Augmentations)
229:
230: /** Start CDATA section. */
231: public void startCDATA(Augmentations augs) throws XNIException {
232: if (fDocumentHandler != null) {
233: fDocumentHandler.startCDATA(augs);
234: }
235: } // startCDATA(Augmentations)
236:
237: /** End CDATA section. */
238: public void endCDATA(Augmentations augs) throws XNIException {
239: if (fDocumentHandler != null) {
240: fDocumentHandler.endCDATA(augs);
241: }
242: } // endCDATA(Augmentations)
243:
244: /** End element. */
245: public void endElement(QName element, Augmentations augs)
246: throws XNIException {
247: if (fDocumentHandler != null) {
248: fDocumentHandler.endElement(element, augs);
249: }
250: } // endElement(QName,Augmentations)
251:
252: /** End document. */
253: public void endDocument(Augmentations augs) throws XNIException {
254: if (fDocumentHandler != null) {
255: fDocumentHandler.endDocument(augs);
256: }
257: } // endDocument(Augmentations)
258:
259: // removed since Xerces-J 2.3.0
260:
261: /** Start document. */
262: public void startDocument(XMLLocator locator, String encoding,
263: Augmentations augs) throws XNIException {
264: startDocument(locator, encoding, null, augs);
265: } // startDocument(XMLLocator,String,Augmentations)
266:
267: /** Start prefix mapping. */
268: public void startPrefixMapping(String prefix, String uri,
269: Augmentations augs) throws XNIException {
270: if (fDocumentHandler != null) {
271: Class cls = fDocumentHandler.getClass();
272: Class[] types = { String.class, String.class,
273: Augmentations.class };
274: try {
275: Method method = cls.getMethod("startPrefixMapping",
276: types);
277: Object[] args = { prefix, uri, augs };
278: method.invoke(fDocumentHandler, args);
279: } catch (NoSuchMethodException e) {
280: // ignore
281: } catch (IllegalAccessException e) {
282: // ignore
283: } catch (InvocationTargetException e) {
284: // ignore
285: }
286: }
287: } // startPrefixMapping(String,String,Augmentations)
288:
289: /** End prefix mapping. */
290: public void endPrefixMapping(String prefix, Augmentations augs)
291: throws XNIException {
292: if (fDocumentHandler != null) {
293: Class cls = fDocumentHandler.getClass();
294: Class[] types = { String.class, Augmentations.class };
295: try {
296: Method method = cls
297: .getMethod("endPrefixMapping", types);
298: Object[] args = { prefix, augs };
299: method.invoke(fDocumentHandler, args);
300: } catch (NoSuchMethodException e) {
301: // ignore
302: } catch (IllegalAccessException e) {
303: // ignore
304: } catch (InvocationTargetException e) {
305: // ignore
306: }
307: }
308: } // endPrefixMapping(String,Augmentations)
309:
310: //
311: // HTMLComponent methods
312: //
313:
314: /**
315: * Returns a list of feature identifiers that are recognized by
316: * this component. This method may return null if no features
317: * are recognized by this component.
318: */
319: public String[] getRecognizedFeatures() {
320: return null;
321: } // getRecognizedFeatures():String[]
322:
323: /**
324: * Returns the default state for a feature, or null if this
325: * component does not want to report a default value for this
326: * feature.
327: */
328: public Boolean getFeatureDefault(String featureId) {
329: return null;
330: } // getFeatureDefault(String):Boolean
331:
332: /**
333: * Returns a list of property identifiers that are recognized by
334: * this component. This method may return null if no properties
335: * are recognized by this component.
336: */
337: public String[] getRecognizedProperties() {
338: return null;
339: } // getRecognizedProperties():String[]
340:
341: /**
342: * Returns the default state for a property, or null if this
343: * component does not want to report a default value for this
344: * property.
345: */
346: public Object getPropertyDefault(String propertyId) {
347: return null;
348: } // getPropertyDefault(String):Object
349:
350: /**
351: * Resets the component. The component can query the component manager
352: * about any features and properties that affect the operation of the
353: * component.
354: *
355: * @param componentManager The component manager.
356: *
357: * @throws XNIException Thrown by component on initialization error.
358: */
359: public void reset(XMLComponentManager componentManager)
360: throws XMLConfigurationException {
361: } // reset(XMLComponentManager)
362:
363: /**
364: * Sets the state of a feature. This method is called by the component
365: * manager any time after reset when a feature changes state.
366: * <p>
367: * <strong>Note:</strong> Components should silently ignore features
368: * that do not affect the operation of the component.
369: *
370: * @param featureId The feature identifier.
371: * @param state The state of the feature.
372: *
373: * @throws XMLConfigurationException Thrown for configuration error.
374: * In general, components should
375: * only throw this exception if
376: * it is <strong>really</strong>
377: * a critical error.
378: */
379: public void setFeature(String featureId, boolean state)
380: throws XMLConfigurationException {
381: } // setFeature(String,boolean)
382:
383: /**
384: * Sets the value of a property. This method is called by the component
385: * manager any time after reset when a property changes value.
386: * <p>
387: * <strong>Note:</strong> Components should silently ignore properties
388: * that do not affect the operation of the component.
389: *
390: * @param propertyId The property identifier.
391: * @param value The value of the property.
392: *
393: * @throws XMLConfigurationException Thrown for configuration error.
394: * In general, components should
395: * only throw this exception if
396: * it is <strong>really</strong>
397: * a critical error.
398: */
399: public void setProperty(String propertyId, Object value)
400: throws XMLConfigurationException {
401: } // setProperty(String,Object)
402:
403: //
404: // Protected static methods
405: //
406:
407: /**
408: * Utility method for merging string arrays for recognized features
409: * and recognized properties.
410: */
411: protected static String[] merge(String[] array1, String[] array2) {
412:
413: // shortcut merge
414: if (array1 == array2) {
415: return array1;
416: }
417: if (array1 == null) {
418: return array2;
419: }
420: if (array2 == null) {
421: return array1;
422: }
423:
424: // full merge
425: String[] array3 = new String[array1.length + array2.length];
426: System.arraycopy(array1, 0, array3, 0, array1.length);
427: System.arraycopy(array2, 0, array3, array1.length,
428: array2.length);
429:
430: return array3;
431:
432: } // merge(String[],String[]):String[]
433:
434: } // class DefaultFilter
|