TldLocationsCachepublic class TldLocationsCache extends Object A container for all tag libraries that are defined "globally"
for the web application.
Tag Libraries can be defined globally in one of two ways:
1. Via elements in web.xml:
the uri and location of the tag-library are specified in
the element.
2. Via packaged jar files that contain .tld files
within the META-INF directory, or some subdirectory
of it. The taglib is 'global' if it has the
element defined.
A mapping between the taglib URI and its associated TaglibraryInfoImpl
is maintained in this container.
Actually, that's what we'd like to do. However, because of the
way the classes TagLibraryInfo and TagInfo have been defined,
it is not currently possible to share an instance of TagLibraryInfo
across page invocations. A bug has been submitted to the spec lead.
In the mean time, all we do is save the 'location' where the
TLD associated with a taglib URI can be found.
When a JSP page has a taglib directive, the mappings in this container
are first searched (see method getLocation()).
If a mapping is found, then the location of the TLD is returned.
If no mapping is found, then the uri specified
in the taglib directive is to be interpreted as the location for
the TLD of this tag library. |
Fields Summary |
---|
private static com.sun.org.apache.commons.logging.Log | log | public static final int | ABS_URIThe types of URI one may specify for a tag library | public static final int | ROOT_REL_URI | public static final int | NOROOT_REL_URI | private static final String | WEB_XML | private static final String | FILE_PROTOCOL | private static final String | JAR_FILE_SUFFIX | private static HashSet | noTldJars | private static HashSet | systemUris | private static HashSet | systemUrisJsf | private HashMap | mappingsThe mapping of the 'global' tag library URI to the location (resource
path) of the TLD associated with that tag library. The location is
returned as a String array:
[0] The location
[1] If the location is a jar file, this is the location of the tld. | private boolean | initialized | private ServletContext | ctxt | private boolean | redeployMode | private org.apache.jasper.Options | options | private boolean | localTldsProcessed | private boolean | useMyFaces |
Constructors Summary |
---|
public TldLocationsCache(ServletContext ctxt, org.apache.jasper.Options options)
//*********************************************************************
// Constructor and Initilizations
/*
* Initializes the set of JARs that are known not to contain any TLDs
*/
systemUrisJsf.add("http://java.sun.com/jsf/core");
systemUrisJsf.add("http://java.sun.com/jsf/html");
systemUris.add("http://java.sun.com/jsp/jstl/core");
// END SJSAS 6384538
/* SJSAS 6384538
this(ctxt, true);
*/
// START SJSAS 6384538
this(ctxt, options, true);
// END SJSAS 6384538
| public TldLocationsCache(ServletContext ctxt, org.apache.jasper.Options options, boolean redeployMode)Constructor.
// END SJSAS 6384538
this.ctxt = ctxt;
// START SJSAS 6384538
this.options = options;
// END SJSAS 6384538
this.redeployMode = redeployMode;
/* GlassFish 747
mappings = new Hashtable();
*/
Boolean b = (Boolean) ctxt.getAttribute("com.sun.faces.useMyFaces");
if (b != null) {
useMyFaces = b.booleanValue();
}
initialized = false;
|
Methods Summary |
---|
public java.lang.String[] | getLocation(java.lang.String uri)Gets the 'location' of the TLD associated with the given taglib 'uri'.
Returns null if the uri is not associated with any tag library 'exposed'
in the web application. A tag library is 'exposed' either explicitly in
web.xml or implicitly via the uri tag in the TLD of a taglib deployed
in a jar file (WEB-INF/lib).
if (!initialized) {
init();
}
return (String[]) mappings.get(uri);
| private java.lang.String | getUriFromTld(java.lang.String resourcePath, java.io.InputStream in)
// Parse the tag library descriptor at the specified resource path
/* SJSAS 6384538
TreeNode tld = new ParserUtils().parseXMLDocument(resourcePath, in);
*/
// START SJSAS 6384538
TreeNode tld = new ParserUtils().parseXMLDocument(
resourcePath, in, options.isValidationEnabled());
// END SJSAS 6384538
TreeNode uri = tld.findChild("uri");
if (uri != null) {
String body = uri.getBody();
if (body != null)
return body;
}
return null;
| private void | init()
if (initialized) return;
// START GlassFish 747
HashMap tldUriToLocationMap = (HashMap) ctxt.getAttribute(
Constants.JSP_TLD_URI_TO_LOCATION_MAP);
if (tldUriToLocationMap != null) {
localTldsProcessed = true;
mappings = tldUriToLocationMap;
} else {
mappings = new HashMap();
}
// END GlassFish 747
try {
/* GlassFish 747
processWebDotXml();
*/
// START Glassfish 747
if (!localTldsProcessed) {
processWebDotXml();
}
// END Glassfish 747
scanJars();
/* GlassFish 747
processTldsInFileSystem("/WEB-INF/");
*/
// START GlassFish 747
if (!localTldsProcessed) {
processTldsInFileSystem("/WEB-INF/");
}
// END Glassfish 747
initialized = true;
} catch (Exception ex) {
throw new JasperException(
Localizer.getMessage("jsp.error.internal.tldinit"),
ex);
}
| private boolean | needScanJar(java.lang.String jarPath, boolean isLocal)
if (isLocal) {
return true;
}
String jarName = jarPath;
int slash = jarPath.lastIndexOf('/");
if (slash >= 0) {
jarName = jarPath.substring(slash + 1);
}
return ((noTldJars == null) || !noTldJars.contains(jarName));
| private void | processTldsInFileSystem(java.lang.String startPath)
Set dirList = ctxt.getResourcePaths(startPath);
if (dirList != null) {
Iterator it = dirList.iterator();
while (it.hasNext()) {
String path = (String) it.next();
if (path.endsWith("/")) {
processTldsInFileSystem(path);
}
if (!path.endsWith(".tld")) {
continue;
}
if (path.startsWith("/WEB-INF/tags/")
&& !path.endsWith("implicit.tld")) {
throw new JasperException(
Localizer.getMessage(
"jsp.error.tldinit.tldInWebInfTags",
path));
}
InputStream stream = ctxt.getResourceAsStream(path);
String uri = null;
try {
uri = getUriFromTld(path, stream);
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
// do nothing
}
}
}
// Add implicit map entry only if its uri is not already
// present in the map
if (uri != null
&& mappings.get(uri) == null
&& !systemUris.contains(uri)
&& (!systemUrisJsf.contains(uri)
|| useMyFaces)) {
mappings.put(uri, new String[] { path, null });
}
}
}
| private void | processWebDotXml()
InputStream is = null;
try {
// Acquire input stream to web application deployment descriptor
String altDDName = (String)ctxt.getAttribute(
Constants.ALT_DD_ATTR);
if (altDDName != null) {
try {
is = new FileInputStream(altDDName);
} catch (FileNotFoundException e) {
if (log.isWarnEnabled()) {
log.warn(Localizer.getMessage(
"jsp.error.internal.filenotfound",
altDDName));
}
}
} else {
is = ctxt.getResourceAsStream(WEB_XML);
/* SJSAS 6396582
if (is == null && log.isWarnEnabled()) {
log.warn(Localizer.getMessage(
"jsp.error.internal.filenotfound",
WEB_XML));
}
*/
}
if (is == null) {
return;
}
// Parse the web application deployment descriptor
TreeNode webtld = null;
// altDDName is the absolute path of the DD
if (altDDName != null) {
webtld = new ParserUtils().parseXMLDocument(altDDName, is);
} else {
webtld = new ParserUtils().parseXMLDocument(WEB_XML, is);
}
// Allow taglib to be an element of the root or jsp-config (JSP2.0)
TreeNode jspConfig = webtld.findChild("jsp-config");
if (jspConfig != null) {
webtld = jspConfig;
}
Iterator taglibs = webtld.findChildren("taglib");
while (taglibs.hasNext()) {
// Parse the next <taglib> element
TreeNode taglib = (TreeNode) taglibs.next();
String tagUri = null;
String tagLoc = null;
TreeNode child = taglib.findChild("taglib-uri");
if (child != null)
tagUri = child.getBody();
// Ignore system tlds in web.xml, for backward compatibility
if (systemUris.contains(tagUri)
|| (!useMyFaces && systemUrisJsf.contains(tagUri))) {
continue;
}
child = taglib.findChild("taglib-location");
if (child != null)
tagLoc = child.getBody();
// Save this location if appropriate
if (tagLoc == null)
continue;
if (uriType(tagLoc) == NOROOT_REL_URI)
tagLoc = "/WEB-INF/" + tagLoc;
String tagLoc2 = null;
if (tagLoc.endsWith(JAR_FILE_SUFFIX)) {
tagLoc = ctxt.getResource(tagLoc).toString();
tagLoc2 = "META-INF/taglib.tld";
}
mappings.put(tagUri, new String[] { tagLoc, tagLoc2 });
}
} finally {
if (is != null) {
try {
is.close();
} catch (Throwable t) {}
}
}
| private void | scanJar(java.net.JarURLConnection conn, boolean ignore)Scans the given JarURLConnection for TLD files located in META-INF
(or a subdirectory of it), adding an implicit map entry to the taglib
map for any TLD that has a element.
JarFile jarFile = null;
String resourcePath = conn.getJarFileURL().toString();
try {
if (redeployMode) {
conn.setUseCaches(false);
}
jarFile = conn.getJarFile();
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
String name = entry.getName();
if (!name.startsWith("META-INF/")) continue;
if (!name.endsWith(".tld")) continue;
InputStream stream = jarFile.getInputStream(entry);
try {
String uri = getUriFromTld(resourcePath, stream);
// Add map entry.
// Override existing entries as we move higher
// up in the classloader delegation chain.
if (uri != null
&& (mappings.get(uri) == null
|| systemUris.contains(uri)
|| (systemUrisJsf.contains(uri)
&& !useMyFaces))) {
mappings.put(uri, new String[]{ resourcePath, name });
}
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
// do nothing
}
}
}
}
} catch (Exception ex) {
if (!redeployMode) {
// if not in redeploy mode, close the jar in case of an error
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
// ignore
}
}
}
if (!ignore) {
throw new JasperException(ex);
}
} finally {
if (redeployMode) {
// if in redeploy mode, always close the jar
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
// ignore
}
}
}
}
| private void | scanJars()
ClassLoader webappLoader
= Thread.currentThread().getContextClassLoader();
ClassLoader loader = webappLoader;
// START Glassfish 747
if (localTldsProcessed) {
if (loader != null) {
loader = loader.getParent();
}
}
// END GlassFish 747
while (loader != null) {
if (loader instanceof URLClassLoader) {
boolean isLocal = (loader == webappLoader);
URL[] urls = ((URLClassLoader) loader).getURLs();
for (int i=0; i<urls.length; i++) {
URLConnection conn = urls[i].openConnection();
if (conn instanceof JarURLConnection) {
if (needScanJar(
((JarURLConnection) conn).getJarFile().getName(),
isLocal)) {
scanJar((JarURLConnection) conn, true);
}
} else {
String urlStr = urls[i].toString();
if (urlStr.startsWith(FILE_PROTOCOL)
&& urlStr.endsWith(JAR_FILE_SUFFIX)
&& needScanJar(urlStr, isLocal)) {
URL jarURL = new URL("jar:" + urlStr + "!/");
scanJar((JarURLConnection) jarURL.openConnection(),
true);
}
}
}
}
loader = loader.getParent();
}
| public static void | setNoTldJars(java.lang.String jarNames)Sets the list of JAR files that are known not to contain any TLDs.
Only shared JAR files (that is, those loaded by a delegation parent
of the webapp's classloader) will be checked against this list.
if (jarNames != null) {
if (noTldJars == null) {
noTldJars = new HashSet<String>();
} else {
noTldJars.clear();
}
StringTokenizer tokenizer = new StringTokenizer(jarNames, ",");
while (tokenizer.hasMoreElements()) {
noTldJars.add(tokenizer.nextToken());
}
}
| public static void | setNoTldJars(java.util.HashSet set)Sets the list of JAR files that are known not to contain any TLDs.
Only shared JAR files (that is, those loaded by a delegation parent
of the webapp's classloader) will be checked against this list.
noTldJars = set;
| public static int | uriType(java.lang.String uri)Returns the type of a URI:
ABS_URI
ROOT_REL_URI
NOROOT_REL_URI
if (uri.indexOf(':") != -1) {
return ABS_URI;
} else if (uri.startsWith("/")) {
return ROOT_REL_URI;
} else {
return NOROOT_REL_URI;
}
|
|