/*
* #!
* Ontopia Navigator
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.utils.ontojsp;
import java.util.Stack;
import javax.servlet.jsp.tagext.TagSupport;
import net.ontopia.topicmaps.nav2.core.NavigatorRuntimeException;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.xml.Slf4jSaxErrorHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* INTERNAL: A Content Handler that reads a JSP file and builds a
* JSP tree of JSPTreeNodeIF objects from a XML instance.
*/
public class JSPContentHandler extends DefaultHandler {
// initialize logging facility
static Logger log = LoggerFactory.getLogger(JSPContentHandler.class.getName());
protected JSPTreeNodeIF root;
protected JSPTreeNodeIF current;
protected JSPTagFactoryIF tagFactory;
protected Stack<String> parents;
protected final boolean useTagPooling;
protected ErrorHandler ehandler;
protected Locator locator;
public JSPContentHandler() {
this(TaglibTagFactory.TAGPOOLING_DEFAULT);
}
public JSPContentHandler(boolean useTagPooling) {
this.root = new JSPTreeNode("ROOT", null, useTagPooling);
this.current = root;
this.parents = new Stack<String>();
this.tagFactory = new TaglibTagFactory(useTagPooling);
this.useTagPooling = useTagPooling;
}
@Override
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
public void register(XMLReader parser) {
parser.setContentHandler(this);
ErrorHandler _ehandler = parser.getErrorHandler();
if (_ehandler == null || (_ehandler instanceof DefaultHandler))
parser.setErrorHandler(getDefaultErrorHandler());
ehandler = parser.getErrorHandler();
}
protected ErrorHandler getDefaultErrorHandler() {
Slf4jSaxErrorHandler ehandler = new Slf4jSaxErrorHandler(log);
ehandler.setIgnoreNamespaceError(true);
return ehandler;
}
@Override
public void startDocument() {
parents.clear();
}
@Override
public void endDocument() {
}
@Override
public void startElement(String uri, String lname, String qname,
Attributes atts) throws SAXException {
// instantiate new node with current node as parent
JSPTreeNodeIF node;
boolean insideKnownTag;
if (TaglibTagFactory.isKnownTag(qname)) {
node = new JSPTreeNode(qname, current, useTagPooling);
// add the attributes to the tree node.
for (int i = 0; i < atts.getLength(); i++)
node.addAttribute(atts.getQName(i), atts.getValue(i));
TagSupport parentTag = current.getTag();
try {
TagSupport tag = tagFactory.getTagInstance(qname, node.getAttributes(),
parentTag);
node.setTag(tag);
} catch (NavigatorRuntimeException e) {
throw new OntopiaRuntimeException(e);
}
insideKnownTag = true;
// log.debug("Created " + node);
} else {
// this is a not know tag, so we treat this as stupid text
// without any nesting
StringBuilder dummyTag = new StringBuilder("<");
dummyTag.append(qname);
for (int i = 0; i < atts.getLength(); i++) {
dummyTag.append(" ").append(atts.getQName(i))
.append("='").append(atts.getValue(i)).append("'");
}
dummyTag.append(">");
node = new JSPContentTreeNode(current, dummyTag.toString());
insideKnownTag = false;
}
// insert the new tree node into the tree
current.addChild(node);
if (insideKnownTag) {
current = node;
parents.push(qname);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch, start, length);
JSPTreeNodeIF node = new JSPContentTreeNode(current, content);
current.addChild(node);
if (log.isDebugEnabled())
log.debug("Created content child: " + node);
}
@Override
public void endElement(String uri, String lname, String qname)
throws SAXException {
if (TaglibTagFactory.isKnownTag(qname)) {
// Sets the current node to refer to the parent of the node
// we are closing.
current = current.getParent();
parents.pop();
} else {
StringBuilder dummyTag = new StringBuilder();
dummyTag.append("</").append(qname).append(">");
JSPTreeNodeIF node = new JSPContentTreeNode(current, dummyTag.toString());
current.addChild(node);
// log.debug("Created content child: " + node);
}
}
// --------------------------------------------------------------
// other methods, not overwritting DefaultHandler methods
// --------------------------------------------------------------
/**
* Returns the root node of the just read-in and built JSPTree.
*/
public JSPTreeNodeIF getRootNode() {
return root;
}
}