Methods Summary |
---|
public void | addApplicationListener(java.lang.String s)
if (log.isDebugEnabled()) {
log.debug( "Add tld listener " + s);
}
if ((isCurrentTldLocal
&& !systemTldUris.contains(currentTldUri)
&& (!systemTldUrisJsf.contains(currentTldUri)
|| useMyFaces))
|| (!isCurrentTldLocal
&& (!systemTldUrisJsf.contains(currentTldUri)
|| !useMyFaces))) {
listeners.add(s);
}
|
private com.sun.org.apache.commons.digester.Digester | createTldDigester()Create (if necessary) and return a Digester configured to process a tag
library descriptor, looking for additional listener classes to be
registered.
/* SJSAS 6384538
return DigesterFactory.newDigester(tldValidation,
tldNamespaceAware,
new TldRuleSet());
*/
// START SJSAS 6384538
return DigesterFactory.newDigester(false,
tldNamespaceAware,
new TldRuleSet());
// END SJSAS 6384538
|
public void | execute()Scan for and configure all tag library descriptors found in this
web application.
long t1=System.currentTimeMillis();
File tldCache=null;
/* CR 6402120
if (context instanceof StandardContext) {
*/
// START CR 6402120
if (log.isDebugEnabled()) {
log.debug("Create/use TLD listener cache? "
+ (isCacheListeners()));
}
// If multiple JVMs are running, then do not create tldCache.ser
// file as it will cause exceptions on the server side
// because of unsynchronized access of tldCache.ser file.
if ((context instanceof StandardContext) && isCacheListeners()) {
// END CR 6402120
File workDir= (File)
((StandardContext)context).getServletContext().getAttribute(Globals.WORK_DIR_ATTR);
tldCache=new File( workDir, "tldCache.ser");
}
// Option to not rescan
if( ! rescan ) {
// find the cache
if( tldCache!= null && tldCache.exists()) {
try {
processCache(tldCache);
return;
} catch (Throwable t) {
log.warn("Error scanning " + tldCache, t);
}
}
}
/*
* Acquire the list of TLD resource paths, possibly embedded in JAR
* files, to be processed
*/
Set resourcePaths = tldScanResourcePaths();
Map jarPaths = getJarPaths();
// Check to see if we can use cached listeners
if (tldCache != null && tldCache.exists()) {
long lastModified = getLastModified(resourcePaths, jarPaths);
if (lastModified < tldCache.lastModified()) {
try {
processCache(tldCache);
return;
} catch (Throwable t) {
log.warn("Error scanning " + tldCache, t);
}
}
}
// Scan each accumulated resource path for TLDs to be processed
Iterator<String> paths = resourcePaths.iterator();
while (paths.hasNext()) {
tldScanTld(paths.next());
}
if (jarPaths != null) {
Iterator<JarPathElement> elems = jarPaths.values().iterator();
while (elems.hasNext()) {
JarPathElement elem = elems.next();
tldScanJar(elem.getJarFile(), elem.getIsLocal());
}
}
String list[] = getTldListeners();
if( tldCache!= null ) {
log.debug( "Saving tld cache: " + tldCache + " " + list.length);
try {
FileOutputStream out=new FileOutputStream(tldCache);
ObjectOutputStream oos=new ObjectOutputStream( out );
oos.writeObject( list );
oos.close();
} catch( IOException ex ) {
ex.printStackTrace();
}
}
if( log.isDebugEnabled() )
log.debug( "Adding tld listeners:" + list.length);
for( int i=0; list!=null && i<list.length; i++ ) {
context.addApplicationListener(list[i]);
}
long t2=System.currentTimeMillis();
if( context instanceof StandardContext ) {
((StandardContext)context).setTldScanTime(t2-t1);
}
// START GlassFish 747
context.getServletContext().setAttribute(
Globals.JSP_TLD_URI_TO_LOCATION_MAP,
tldUriToLocationMap);
// END GlassFish 747
|
public org.apache.catalina.Context | getContext()
return context;
|
private java.util.Map | getJarPaths()Returns a map of the paths to all JAR files that are accessible to the
webapp and will be scanned for TLDs and their listeners.
The map always includes all the JARs under WEB-INF/lib, as well as
shared JARs in the classloader delegation chain of the webapp's
classloader.
The latter constitutes a Tomcat-specific extension to the TLD search
order defined in the JSP spec. It allows tag libraries packaged as JAR
files to be shared by web applications by simply dropping them in a
location that all web applications have access to (e.g.,
/common/lib).
The set of shared JARs to be scanned for TLDs is narrowed down by
the noTldListeners class variable, which contains the names
of JARs that are known not to contain any TLDs that declare servlet
listeners.
HashMap jarPathMap = null;
ClassLoader webappLoader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = webappLoader;
while (loader != null) {
if (loader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) loader).getURLs();
for (int i=0; i<urls.length; i++) {
// Expect file URLs
// This is definitely not as clean as using JAR URLs either
// over file or the custom jndi handler, but a lot less
// buggy overall
File file = new File(
RequestUtil.URLDecode(urls[i].getFile()));
try {
file = file.getCanonicalFile();
} catch (IOException e) {
// Ignore
}
if (!file.exists()) {
continue;
}
String path = file.getAbsolutePath();
if (!path.endsWith(".jar")) {
continue;
}
/*
* Scan all JARs from WEB-INF/lib, plus any shared JARs
* that are not known not to contain any TLDs with
* listeners
*/
if (loader == webappLoader
|| noTldListeners == null
|| !noTldListeners.contains(file.getName())) {
JarPathElement elem = new JarPathElement(
file, loader == webappLoader);
if (jarPathMap == null) {
jarPathMap = new HashMap();
jarPathMap.put(path, elem);
} else if (!jarPathMap.containsKey(path)) {
jarPathMap.put(path, elem);
}
}
}
}
// START SJSAS 8.1 5049111
if ( scanParent || context.isJsfApplication() ) {
// END SJSAS 8.1 5049111
loader = loader.getParent();
// START SJSAS 8.1 5049111
} else {
loader = null;
}
// END SJSAS 8.1 5049111
}
return jarPathMap;
|
private long | getLastModified(java.util.Set resourcePaths, java.util.Map jarPaths)
long lastModified = 0;
Iterator paths = resourcePaths.iterator();
while (paths.hasNext()) {
String path = (String) paths.next();
URL url = context.getServletContext().getResource(path);
if (url == null) {
log.debug( "Null url "+ path );
break;
}
long lastM = url.openConnection().getLastModified();
if (lastM > lastModified) lastModified = lastM;
if (log.isDebugEnabled()) {
log.debug( "Last modified " + path + " " + lastM);
}
}
if (jarPaths != null) {
Iterator<JarPathElement> elems = jarPaths.values().iterator();
while (elems.hasNext()) {
JarPathElement elem = elems.next();
File jarFile = elem.getJarFile();
long lastM = jarFile.lastModified();
if (lastM > lastModified) lastModified = lastM;
if (log.isDebugEnabled()) {
log.debug("Last modified " + jarFile.getAbsolutePath()
+ " " + lastM);
}
}
}
return lastModified;
|
public static boolean | getScanParentTldListener()
return scanParent;
|
public java.lang.String[] | getTldListeners()
String result[]=new String[listeners.size()];
listeners.toArray(result);
return result;
|
public boolean | getTldNamespaceAware()Get the server.xml attribute's xmlNamespaceAware.
return tldNamespaceAware;
|
public boolean | getTldValidation()Get the server.xml attribute's xmlValidation.
return tldValidation;
|
public static boolean | isCacheListeners()Indicates if a serialized cache of listeners is to be created and used
return cacheListeners;
|
public boolean | isRescan()
return rescan;
|
private void | processCache(java.io.File tldCache)Reads the cache of listeners specified in TLD files.
FileInputStream in=new FileInputStream(tldCache);
ObjectInputStream ois=new ObjectInputStream( in );
String list[]=(String [])ois.readObject();
if( log.isDebugEnabled() ) {
log.debug("Reusing tldCache " + tldCache + " " + list.length);
}
for( int i=0; list!=null && i<list.length; i++ ) {
// Load the listener class. Failure to do so is an indication
// that the cache has become stale, in which case it must be
// ignored. See GlassFish Issue 2653.
context.getLoader().getClassLoader().loadClass(list[i]);
context.addApplicationListener(list[i]);
}
ois.close();
|
public static void | setCacheListeners(boolean cache)Sets the flag that indicates whether to create/use a serialized cache of
listeners
cacheListeners = cache;
|
public void | setContext(org.apache.catalina.Context context)
this.context = context;
this.useMyFaces = ((StandardContext) context).isUseMyFaces();
|
public static void | setNoTldListeners(java.lang.String jarNames)Sets the list of JAR files that are known not to contain any
TLDs that declare servlet listeners.
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 (noTldListeners == null) {
noTldListeners = new HashSet<String>();
} else {
noTldListeners.clear();
}
StringTokenizer tokenizer = new StringTokenizer(jarNames, ",");
while (tokenizer.hasMoreElements()) {
noTldListeners.add(tokenizer.nextToken());
}
}
|
public static void | setNoTldListeners(java.util.HashSet set)Sets the list of JAR files that are known not to contain any
TLDs that declare servlet listeners.
Only shared JAR files (that is, those loaded by a delegation parent
of the webapp's classloader) will be checked against this list.
noTldListeners = set;
|
public void | setRescan(boolean rescan)
this.rescan = rescan;
|
public static void | setScanParentTldListener(boolean scan)Scan the parent when searching for TLD listeners.
scanParent = scan;
|
public static void | setSingleProcess(boolean isSingleProcess)
cacheListeners = isSingleProcess;
|
public void | setTldNamespaceAware(boolean tldNamespaceAware)Set the namespace aware feature of the XML parser used when
parsing xml instances.
this.tldNamespaceAware = tldNamespaceAware;
|
public void | setTldUri(java.lang.String uri)
this.currentTldUri = uri;
// START GlassFish 747
/*
* Add the mapping for the given URI only if
* - the corresponding TLD is local, and
* - the URI is not one of the standard (i.e., JSTL or JSF) ones, and
* - the URI is not already mapped (this check is necessary because
* taglibs specified in web.xml are supposed to take precedence)
*/
if (isCurrentTldLocal
&& !systemTldUris.contains(currentTldUri)
&& (!systemTldUrisJsf.contains(currentTldUri)
|| useMyFaces)
&& tldUriToLocationMap.get(currentTldUri) == null) {
String[] currentTldLocation = new String[2];
if (currentTldResourcePath != null) {
currentTldLocation[0] = currentTldResourcePath;
} else if (currentTldJarFile != null
&& currentTldJarEntryName != null) {
currentTldLocation[0] = "file:" + currentTldJarFile;
currentTldLocation[1] = currentTldJarEntryName;
}
tldUriToLocationMap.put(currentTldUri, currentTldLocation);
}
// END GlassFish 747
|
public void | setTldValidation(boolean tldValidation)Set the validation feature of the XML parser used when
parsing xml instances.
this.tldValidation = tldValidation;
|
public void | setUseMyFaces(boolean useMyFaces)
// --------------------------------------------------------- Public Methods
this.useMyFaces = useMyFaces;
|
private void | tldScanJar(java.io.File file)Scans all TLD entries in the given JAR for application listeners.
tldScanJar(file, false);
|
private void | tldScanJar(java.io.File file, boolean isLocal)
JarFile jarFile = null;
String name = null;
String jarPath = file.getAbsolutePath();
try {
jarFile = new JarFile(file);
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
name = entry.getName();
if (!name.startsWith("META-INF/")) {
continue;
}
if (!name.endsWith(".tld")) {
continue;
}
if (log.isTraceEnabled()) {
log.trace(" Processing TLD at '" + name + "'");
}
// START GlassFish 747
currentTldJarFile = jarPath;
currentTldJarEntryName = name;
// END GlassFish 747
try {
tldScanStream(new InputSource(jarFile.getInputStream(entry)),
isLocal);
} catch (Exception e) {
log.error(sm.getString("contextConfig.tldEntryException",
name, jarPath, context.getPath()),
e);
}
}
} catch (Exception e) {
log.error(sm.getString("contextConfig.tldJarException",
jarPath, context.getPath()),
e);
} finally {
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
// Ignore
}
}
}
|
private java.util.Set | tldScanResourcePaths()Accumulate and return a Set of resource paths to be analyzed for
tag library descriptors. Each element of the returned set will be
the context-relative path to either a tag library descriptor file,
or to a JAR file that may contain tag library descriptors in its
META-INF subdirectory.
if (log.isTraceEnabled()) {
log.trace(" Accumulating TLD resource paths");
}
Set resourcePaths = new HashSet();
// Accumulate resource paths explicitly listed in the web application
// deployment descriptor
if (log.isTraceEnabled()) {
log.trace(" Scanning <taglib> elements in web.xml");
}
String taglibs[] = context.findTaglibs();
for (int i = 0; i < taglibs.length; i++) {
String resourcePath = context.findTaglib(taglibs[i]);
// FIXME - Servlet 2.4 DTD implies that the location MUST be
// a context-relative path starting with '/'?
if (!resourcePath.startsWith("/")) {
resourcePath = "/WEB-INF/" + resourcePath;
}
if (log.isTraceEnabled()) {
log.trace(" Adding path '" + resourcePath +
"' for URI '" + taglibs[i] + "'");
}
// START GlassFish 747
tldUriToLocationMap.put(taglibs[i],
new String[] { resourcePath, null});
// END GlassFish 747
resourcePaths.add(resourcePath);
}
DirContext resources = context.getResources();
if (resources != null) {
tldScanResourcePathsWebInf(resources, "/WEB-INF", resourcePaths);
}
// Return the completed set
return (resourcePaths);
|
private void | tldScanResourcePathsWebInf(javax.naming.directory.DirContext resources, java.lang.String rootPath, java.util.Set tldPaths)
if (log.isTraceEnabled()) {
log.trace(" Scanning TLDs in " + rootPath + " subdirectory");
}
try {
NamingEnumeration items = resources.list(rootPath);
while (items.hasMoreElements()) {
NameClassPair item = (NameClassPair) items.nextElement();
String resourcePath = rootPath + "/" + item.getName();
if (resourcePath.startsWith("/WEB-INF/tags")) {
continue;
}
if (resourcePath.endsWith(".tld")) {
if (log.isTraceEnabled()) {
log.trace(" Adding path '" + resourcePath + "'");
}
tldPaths.add(resourcePath);
} else {
tldScanResourcePathsWebInf(resources, resourcePath,
tldPaths);
}
}
} catch (NamingException e) {
; // Silent catch: it's valid that no /WEB-INF directory exists
}
|
private void | tldScanStream(org.xml.sax.InputSource resourceStream)Scan the TLD contents in the specified input stream, and register
any application event listeners found there. NOTE - It is
the responsibility of the caller to close the InputStream after this
method returns.
tldScanStream(resourceStream, false);
|
private void | tldScanStream(org.xml.sax.InputSource resourceStream, boolean isLocal)
if (tldDigester == null){
tldDigester = createTldDigester();
}
synchronized (tldDigester) {
try {
tldDigester.push(this);
isCurrentTldLocal = isLocal;
tldDigester.parse(resourceStream);
} finally {
isCurrentTldLocal = false;
currentTldUri = null;
// START GlassFish 747
currentTldJarFile = null;
currentTldJarEntryName = null;
currentTldResourcePath = null;
// END GlassFish 747
tldDigester.push(null);
tldDigester.clear();
}
}
|
private void | tldScanTld(java.lang.String resourcePath)Scan the TLD contents at the specified resource path, and register
any application event listeners found there.
if (log.isDebugEnabled()) {
log.debug(" Scanning TLD at resource path '" + resourcePath + "'");
}
InputStream tldStream =
context.getServletContext().getResourceAsStream(resourcePath);
if (tldStream == null) {
throw new ServletException
(sm.getString("contextConfig.tldResourcePath",
resourcePath));
}
InputSource inputSource = new InputSource(tldStream);
// START GlassFish 747
currentTldResourcePath = resourcePath;
// END GlassFish 747
try {
tldScanStream(inputSource, true);
} catch (Exception e) {
throw new ServletException
(sm.getString("contextConfig.tldFileException", resourcePath,
context.getPath()),
e);
}
|