/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.jsp;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.xml.QName;
import javax.servlet.jsp.tagext.TagInfo;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Logger;
/**
* Stores the information for the .tags
*/
public class ParseTagManager {
static final L10N L = new L10N(ParseTagManager.class);
private static final Logger log
= Logger.getLogger(ParseTagManager.class.getName());
private JspResourceManager _resourceManager;
private TaglibManager _taglibManager;
private TagFileManager _tagFileManager;
private HashMap<QName,TagInfo> _tagMap = new HashMap<QName,TagInfo>();
private HashMap<String,Taglib> _taglibMap = new HashMap<String,Taglib>();
public ParseTagManager(JspResourceManager resourceManager,
TaglibManager taglibManager,
TagFileManager tagFileManager)
throws JspParseException, IOException
{
_resourceManager = resourceManager;
_taglibManager = taglibManager;
_tagFileManager = tagFileManager;
}
/**
* Analyzes the tag.
*/
public synchronized AnalyzedTag analyzeTag(Class cl)
{
return _taglibManager.analyzeTag(cl);
}
/**
* Returns the tag with the given qname.
*/
public synchronized TagInfo getTag(QName qname)
throws JspParseException
{
TagInfo tag = getTagImpl(qname);
if (tag instanceof TagInfoImpl)
((TagInfoImpl) tag).validate();
return tag;
}
/**
* Temporary tag info for recursive tags
*/
TagInfo addTempTagInfo(QName qname, TagInfo info)
{
if (_tagMap.get(qname) == null)
_tagMap.put(qname, info);
return _tagMap.get(qname);
}
/**
* Returns the tag with the given qname.
*/
private TagInfo getTagImpl(QName qname)
throws JspParseException
{
TagInfo tag = _tagMap.get(qname);
if (tag != null)
return tag;
tag = _tagFileManager.getTag(qname.getPrefix(),
qname.getLocalName(),
qname.getNamespaceURI());
_tagMap.put(qname, tag);
if (tag != null)
return tag;
Taglib taglib = addTaglib(qname);
if (taglib == null)
return null;
String name = qname.getName();
String tail = qname.getLocalName();
if (qname.getNamespaceURI() == null) {
int p = name.lastIndexOf(':');
if (p < 0)
return null;
tail = name.substring(p + 1);
}
if (taglib != null)
tag = taglib.getTag(tail);
if (tag == null) {
String tagLocation = taglib.getTagFilePath(tail);
Path path = taglib.getPath();
if (path != null && tagLocation != null) {
path = path.lookup(tagLocation);
tag = _tagFileManager.getTag(path, qname.getPrefix(), tagLocation);
if (tag != null) {
return tag;
}
}
if (tagLocation != null) {
tag = _tagFileManager.getTag(qname.getPrefix(), tagLocation);
if (tag == null)
throw new JspParseException(L.l("'{0}' is an unknown tag-file in tag library '{1}'.",
tagLocation, taglib.getURI()));
}
}
if (tag == null)
throw new JspParseException(L.l("'{0}' is an unknown tag in tag library '{1}'.",
tail, taglib.getURI()));
_tagMap.put(qname, tag);
return tag;
}
/**
* Returns the tag with the given qname.
*/
public synchronized Class getTagClass(QName qname)
throws Exception
{
TagInfo tagInfo = getTag(qname);
if (tagInfo == null)
return null;
String className = tagInfo.getTagClassName();
if (className != null)
return _tagFileManager.loadClass(className);
else
return null;
}
public synchronized Taglib addTaglib(QName qname)
throws JspParseException
{
String prefix = qname.getPrefix();
Taglib taglib = (Taglib) _taglibMap.get(prefix);
if (_taglibMap.get(prefix) != null)
return taglib;
String uri = qname.getNamespace();
taglib = addTaglib(prefix, uri);
_taglibMap.put(prefix, taglib);
return taglib;
}
/**
* Lookup and add a taglib based on a prefix and uri
*/
public synchronized Taglib addTaglib(String prefix, String uri)
throws JspParseException
{
Taglib taglib = null;
boolean hasTld = false;
if (uri == null)
return null;
else if (uri.startsWith("urn:jsptagdir:")) {
String tagDir = uri.substring("urn:jsptagdir:".length());
taglib = addTaglibDir(prefix, tagDir);
hasTld = true;
if (taglib == null) {
throw error(L.l("'{0}' has no matching tag. The taglib uri must match a <uri> element in a taglib.tld.", uri));
}
}
else {
if (uri.startsWith("urn:jsptld:")) {
hasTld = true;
uri = uri.substring("urn:jsptld:".length());
}
String location = uri;
taglib = _taglibManager.getTaglib(prefix, uri, location);
if (hasTld && taglib == null) {
throw error(L.l("'{0}' has no matching tag. The taglib uri must match a <uri> element in a taglib.tld.", uri));
}
}
return taglib;
}
/**
* Adds a taglib.
*/
public synchronized Taglib addTaglibDir(String prefix, String dir)
throws JspParseException
{
return _taglibManager.getTaglibDir(prefix, dir);
}
/**
* Adds a taglib.
*/
public synchronized Taglib addTaglib(String prefix,
String uri,
String location)
throws JspParseException
{
Taglib taglib = _taglibManager.getTaglib(prefix, uri, location);
return addTaglib(taglib);
}
private Taglib addTaglib(Taglib taglib)
throws JspParseException
{
if (taglib == null)
return null;
taglib = taglib.copy();
for (Taglib oldTaglib : _taglibMap.values()) {
if (oldTaglib != null) {
oldTaglib.addTaglib(taglib);
taglib.addTaglib(oldTaglib);
}
}
_taglibMap.put(taglib.getPrefixString(), taglib);
return taglib;
}
public boolean hasTags()
{
return _taglibMap != null && _taglibMap.size() > 1;
}
public JspParseException error(String message)
{
return new JspParseException(message);
}
}