001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.car;
007:
008: import org.apache.commons.logging.Log;
009: import org.apache.commons.logging.LogFactory;
010: import org.xml.sax.Attributes;
011: import org.xml.sax.ContentHandler;
012: import org.xml.sax.SAXException;
013: import org.xml.sax.helpers.DefaultHandler;
014:
015: /**
016: * Handles reading the extension tags in the descriptor. These tags
017: * contain extension specific content that is foreign to the
018: * deployment descriptor but understood by the handler class declared
019: * by the extension tag. Upon entering an extension block the declared
020: * handler class will be instantiated, the startDocument method will
021: * be call indicating to the class that parsing of the content of its
022: * extension block will be forthcoming. All events within the block
023: * are then passed to the handler until the block is exited at which
024: * point the endDocument method is called. Neither the startElement
025: * nor the endElement events for the enclosing extension element are
026: * passed to the handler class. It only sees events for content within
027: * the block.
028: *
029: * @author Mark Boyd {@link <a href="mailto:mark.boyd@engineer.com">mark.boyd@engineer.com</a>}
030: * @version $Revision: 36690 $
031: */
032: class ExtensionTagHandler extends DefaultHandler {
033: private static final Log log = LogFactory
034: .getLog(ExtensionTagHandler.class);
035: private ContentHandler extHandler = null;
036: private ParsingContext ctx = null;
037:
038: public ExtensionTagHandler(ParsingContext ctx) {
039: this .ctx = ctx;
040: }
041:
042: /**
043: Passes character events to an extension block's declared handler
044: if within an extension block and the handler was successfully
045: instantiated.
046: */
047: public void characters(char[] ch, int start, int length)
048: throws SAXException {
049: if (extHandler != null)
050: extHandler.characters(ch, start, length);
051: }
052:
053: /**
054: Receives startElement events watching for entry into an extension
055: block so that it can instantiate a declared handler for that block
056: and pass events within the block to that handler.
057: */
058: public void startElement(String namespaceURI, String localName,
059: String qName, Attributes atts) throws SAXException {
060: if (extHandler != null)
061: extHandler.startElement(namespaceURI, localName, qName,
062: atts);
063:
064: if (qName.equals(DescriptorHandler.EXTENSION_TAG_NAME)
065: && ctx.getPath().equals(DescriptorHandler.EXTENSIONS)) {
066: // entering ext block so clean out old if around, make sure
067: // that we haven't already processed this guy, and
068: // get the handler for this block ready to roll
069: extHandler = null;
070:
071: String handlerClass = atts.getValue("contentHandler");
072:
073: if (handlerClass == null) {
074: log.error("Ignoring invalid extension while "
075: + "processing deployment descriptor for "
076: + ctx.getJarFile().getName()
077: + ". Attribute 'contentHandler' must be "
078: + "specified.");
079: return;
080: }
081: // now lets load and instantiate the handler
082: Class c = null;
083: Object obj = null;
084:
085: try {
086: CarResources cRes = CarResources.getInstance();
087: ClassLoader cl = cRes.getClassLoader();
088: c = cl.loadClass(handlerClass);
089: } catch (ClassNotFoundException clfe) {
090: log.error("Specified contentHandler class "
091: + handlerClass
092: + " not found. Ignoring extension block "
093: + "in deployment descriptor of "
094: + ctx.getJarFile().getName() + ".");
095: return;
096: }
097: /*
098: * The following throwable check was added to prevent the
099: * CarResources from failing to load with a NoClassDefFound error
100: * when a CAR was installed that was compile on a latter JVM than
101: * the one running the system. The result is that an
102: * UnsupportedClassVersionError occurs which passes through the
103: * checks for ClassNotFoundException and causes CarResources'
104: * static initializer to fail resulting in a misleading
105: * NoClassDefFoundError showing in the browser with no indication
106: * as to the real underlying cause.
107: */
108: catch (Throwable t) {
109: log.error(
110: "Error occurred loading specified contentHandler class "
111: + handlerClass
112: + ". Ignoring extension block "
113: + "in deployment descriptor of "
114: + ctx.getJarFile().getName() + ".", t);
115: return;
116: }
117: try {
118: obj = c.newInstance();
119: } catch (Exception e) {
120: log.error("Unable to create specified "
121: + "contentHandler class " + handlerClass
122: + " for extension block"
123: + " in deployment descriptor of "
124: + ctx.getJarFile().getName()
125: + ". Ignoring extension. Details: " + e);
126: return;
127: }
128: try {
129: extHandler = (ContentHandler) obj;
130: } catch (ClassCastException cce) {
131: log.error("Specified contentHandler class "
132: + handlerClass
133: + " for extension in deployment "
134: + "descriptor of " + ctx.getJarFile().getName()
135: + " does not implement ContentHandler. "
136: + "Ignoring extension.");
137: return;
138: }
139:
140: extHandler.startDocument();
141: }
142: }
143:
144: /**
145: Receives end element calls passing them to the declared handler if
146: within an extension block or removing the current handler when an
147: extension block is exited.
148: */
149: public void endElement(String namespaceURI, String localName,
150: String qName) throws SAXException {
151: if (qName.equals(DescriptorHandler.EXTENSION_TAG_NAME)
152: && ctx.getPath().equals(DescriptorHandler.EXTENSIONS)) {
153: // leaving ext block so clean tell the handler that its
154: // document is finished and then remove the handler.
155: if (extHandler != null)
156: extHandler.endDocument();
157:
158: extHandler = null;
159: }
160:
161: // while within ext block handler will be non-null and should
162: // receive all events.
163: if (extHandler != null)
164: extHandler.endElement(namespaceURI, localName, qName);
165: }
166: }
|