/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.jasper.servlet;
/** * Scans for and loads Tag Library Descriptors contained in a web application.
*/ publicclass TldScanner { privatefinal Log log = LogFactory.getLog(TldScanner.class); // must not be static privatestaticfinal String MSG = "org.apache.jasper.servlet.TldScanner"; privatestaticfinal String TLD_EXT = ".tld"; privatestaticfinal String WEB_INF = "/WEB-INF/"; privatefinal ServletContext context; privatefinal TldParser tldParser; privatefinal Map<String, TldResourcePath> uriTldResourcePathMap = new HashMap<>(); privatefinal Map<TldResourcePath, TaglibXml> tldResourcePathTaglibXmlMap = new HashMap<>(); privatefinal List<String> listeners = new ArrayList<>();
/** * Initialise with the application's ServletContext. * * @param context the application's servletContext * @param namespaceAware should the XML parser used to parse TLD files be * configured to be name space aware * @param validation should the XML parser used to parse TLD files be * configured to use validation * @param blockExternal should the XML parser used to parse TLD files be * configured to be block references to external * entities
*/ public TldScanner(ServletContext context, boolean namespaceAware, boolean validation, boolean blockExternal) { this.context = context;
this.tldParser = new TldParser(namespaceAware, validation, blockExternal);
}
/** * Scan for TLDs in all places defined by the specification: * <ol> * <li>Tag libraries defined by the platform</li> * <li>Entries from <jsp-config> in web.xml</li> * <li>A resources under /WEB-INF</li> * <li>In jar files from /WEB-INF/lib</li> * <li>Additional entries from the container</li> * </ol> * * @throws IOException if there was a problem scanning for or loading a TLD * @throws SAXException if there was a problem parsing a TLD
*/ publicvoid scan() throws IOException, SAXException {
scanPlatform();
scanJspConfig();
scanResourcePaths(WEB_INF);
scanJars();
}
/** * Returns the map of URI to TldResourcePath built by this scanner. * * @return the map of URI to TldResourcePath
*/ public Map<String, TldResourcePath> getUriTldResourcePathMap() { return uriTldResourcePathMap;
}
/** * Returns the map of TldResourcePath to parsed XML files built by this * scanner. * * @return the map of TldResourcePath to parsed XML files
*/ public Map<TldResourcePath,TaglibXml> getTldResourcePathTaglibXmlMap() { return tldResourcePathTaglibXmlMap;
}
/** * Returns a list of all listeners declared by scanned TLDs. * * @return a list of listener class names
*/ public List<String> getListeners() { return listeners;
}
/** * Set the class loader used by the digester to create objects as a result * of this scan. Normally this only needs to be set when using JspC. * * @param classLoader Class loader to use when creating new objects while * parsing TLDs
*/ publicvoid setClassLoader(ClassLoader classLoader) {
tldParser.setClassLoader(classLoader);
}
/** * Scan for TLDs required by the platform specification.
*/ protectedvoid scanPlatform() {
}
/** * Scan for TLDs defined in <jsp-config>. * @throws IOException Error reading resources * @throws SAXException XML parsing error
*/ protectedvoid scanJspConfig() throws IOException, SAXException {
JspConfigDescriptor jspConfigDescriptor = context.getJspConfigDescriptor(); if (jspConfigDescriptor == null) { return;
}
Collection<TaglibDescriptor> descriptors = jspConfigDescriptor.getTaglibs(); for (TaglibDescriptor descriptor : descriptors) {
String taglibURI = descriptor.getTaglibURI();
String resourcePath = descriptor.getTaglibLocation(); // Note: Whilst the Servlet 2.4 DTD implies that the location must // be a context-relative path starting with '/', JSP.7.3.6.1 states // explicitly how paths that do not start with '/' should be // handled. if (!resourcePath.startsWith("/")) {
resourcePath = WEB_INF + resourcePath;
} if (uriTldResourcePathMap.containsKey(taglibURI)) {
log.warn(Localizer.getMessage(MSG + ".webxmlSkip",
resourcePath,
taglibURI)); continue;
}
if (log.isTraceEnabled()) {
log.trace(Localizer.getMessage(MSG + ".webxmlAdd",
resourcePath,
taglibURI));
}
URL url = context.getResource(resourcePath); if (url != null) {
TldResourcePath tldResourcePath; if (resourcePath.endsWith(".jar")) { // if the path points to a jar file, the TLD is presumed to be // inside at META-INF/taglib.tld
tldResourcePath = new TldResourcePath(url, resourcePath, "META-INF/taglib.tld");
} else {
tldResourcePath = new TldResourcePath(url, resourcePath);
} // parse TLD but store using the URI supplied in the descriptor
TaglibXml tld = tldParser.parse(tldResourcePath);
uriTldResourcePathMap.put(taglibURI, tldResourcePath);
tldResourcePathTaglibXmlMap.put(tldResourcePath, tld); if (tld.getListeners() != null) {
listeners.addAll(tld.getListeners());
}
} else {
log.warn(Localizer.getMessage(MSG + ".webxmlFailPathDoesNotExist",
resourcePath,
taglibURI)); continue;
}
}
}
/** * Scan web application resources for TLDs, recursively. * * @param startPath the directory resource to scan * @throws IOException if there was a problem scanning for or loading a TLD * @throws SAXException if there was a problem parsing a TLD
*/ protectedvoid scanResourcePaths(String startPath) throws IOException, SAXException {
boolean found = false;
Set<String> dirList = context.getResourcePaths(startPath); if (dirList != null) { for (String path : dirList) { if (path.startsWith("/WEB-INF/classes/")) { // Skip: JSP.7.3.1
} elseif (path.startsWith("/WEB-INF/lib/")) { // Skip: JSP.7.3.1
} elseif (path.endsWith("/")) {
scanResourcePaths(path);
} elseif (path.startsWith("/WEB-INF/tags/")) { // JSP 7.3.1: in /WEB-INF/tags only consider implicit.tld if (path.endsWith("/implicit.tld")) {
found = true;
parseTld(path);
}
} elseif (path.endsWith(TLD_EXT)) {
found = true;
parseTld(path);
}
}
} if (found) { if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage("jsp.tldCache.tldInResourcePath", startPath));
}
} else { if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage("jsp.tldCache.noTldInResourcePath", startPath));
}
}
}
/** * Scan for TLDs in JARs in /WEB-INF/lib.
*/ publicvoid scanJars() {
JarScanner scanner = JarScannerFactory.getJarScanner(context);
TldScannerCallback callback = new TldScannerCallback();
scanner.scan(JarScanType.TLD, context, callback); if (callback.scanFoundNoTLDs()) {
log.info(Localizer.getMessage("jsp.tldCache.noTldSummary"));
}
}
@Override publicvoid scanWebInfClasses() throws IOException { // This is used when scanAllDirectories is enabled and one or more // JARs have been unpacked into WEB-INF/classes as happens with some // IDEs.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.