Skip to content

Commits on Source 4

......@@ -33,6 +33,14 @@
# will be redirected.
# Default is $CATALINA_BASE/logs/catalina.out
#
# CATALINA_OUT_CMD (Optional) Command which will be executed and receive
# as its stdin the stdout and stderr from the Tomcat java
# process. If CATALINA_OUT_CMD is set, the value of
# CATALINA_OUT will be ignored.
# No default.
# Example (all one line)
# CATALINA_OUT_CMD="cronolog $CATALINA_BASE/logs/catalina.%Y-%m-%d.out >/dev/null 2>&1"
#
# CATALINA_OPTS (Optional) Java runtime options used when the "start",
# "run" or "debug" command is executed.
# Include here and not in JAVA_OPTS all options, that should
......@@ -443,13 +451,23 @@ elif [ "$1" = "start" ] ; then
fi
shift
if [ -z "$CATALINA_OUT_CMD" ] ; then
touch "$CATALINA_OUT"
catalina_out_command=">> \"$CATALINA_OUT\" 2>&1"
else
catalina_out_command="| $CATALINA_OUT_CMD"
fi
if [ ! -z "$CATALINA_PID" ]; then
catalina_pid_file="$CATALINA_PID"
else
catalina_pid_file=/dev/null
fi
if [ "$1" = "-security" ] ; then
if [ $have_tty -eq 1 ]; then
echo "Using Security Manager"
fi
shift
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......@@ -458,24 +476,20 @@ elif [ "$1" = "start" ] ; then
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" 2>&1 "&"
2\>\&1 \& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
else
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
eval \{ $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" 2>&1 "&"
2\>\&1 \& echo \$! \>\"$catalina_pid_file\" \; \} $catalina_out_command "&"
fi
if [ ! -z "$CATALINA_PID" ]; then
echo $! > "$CATALINA_PID"
fi
echo "Tomcat started."
elif [ "$1" = "stop" ] ; then
......
......@@ -127,7 +127,7 @@ if $cygwin; then
JRE_HOME=`cygpath --absolute --windows "$JRE_HOME"`
CATALINA_HOME=`cygpath --absolute --windows "$CATALINA_HOME"`
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
[ -n "$JAVA_ENDORSED_DIRS" ] && JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
fi
# Java 9 no longer supports the java.endorsed.dirs
......
......@@ -25,7 +25,7 @@
# ----- Version Control Flags -----
version.major=8
version.minor=5
version.build=35
version.build=37
version.patch=0
version.suffix=
......@@ -140,19 +140,19 @@ jdt.loc.1=http://archive.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj
jdt.loc.2=http://download.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj-${jdt.version}.jar
# ----- Tomcat native library -----
tomcat-native.version=1.2.18
tomcat-native.version=1.2.19
tomcat-native.src.checksum.enabled=true
tomcat-native.src.checksum.algorithm=SHA-512
tomcat-native.src.checksum.value=66481c1f36dc7ea909bf8d55075a232bf6dea3300b56d36415b13da4aefbee16cb52456f3d44b4a2b09b43cd8c7df628145a0623b9cdfa322bc2432e6c44827f
tomcat-native.src.checksum.value=7d69acd5dd684eee9a85c08357b7288a9f083c15a12a9524ba6344f1b9dcdc6ccc512a37b64b9f15b0e697609833e6c68591a60976dcfecce124ec29eb532dba
tomcat-native.win.checksum.enabled=true
tomcat-native.win.checksum.algorithm=SHA-512
tomcat-native.win.checksum.value=979158411b696360fd7efee1df51f4349215fb94df34bae73c7ce98afc45ad3937829c58b7ecf4785d587a90f90d50ec438a96bb166f407a7c831903d953ad55
tomcat-native.win.checksum.value=0b6349303b84632f4ce053e5ed1390571c17748f3527091936a197dcc9a686f768f913e86a431fe13dc7e0e1c3152fd13a5e501fbf95e82a096b27da6b942239
tomcat-native.home=${base.path}/tomcat-native-${tomcat-native.version}
tomcat-native.tar.gz=${tomcat-native.home}/tomcat-native.tar.gz
tomcat-native.loc.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz
tomcat-native.loc.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz
tomcat-native.win.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1-win32-bin.zip
tomcat-native.win.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1-win32-bin.zip
tomcat-native.win.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1a-win32-bin.zip
tomcat-native.win.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1a-win32-bin.zip
# ----- NSIS, version 3.0 or later -----
nsis.version=3.03
......
......@@ -25,21 +25,26 @@ handlers = 1catalina.org.apache.juli.AsyncFileHandler, 2localhost.org.apache.jul
1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
1catalina.org.apache.juli.AsyncFileHandler.encoding = UTF-8
2localhost.org.apache.juli.AsyncFileHandler.level = FINE
2localhost.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.AsyncFileHandler.prefix = localhost.
2localhost.org.apache.juli.AsyncFileHandler.encoding = UTF-8
3manager.org.apache.juli.AsyncFileHandler.level = FINE
3manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
3manager.org.apache.juli.AsyncFileHandler.prefix = manager.
3manager.org.apache.juli.AsyncFileHandler.encoding = UTF-8
4host-manager.org.apache.juli.AsyncFileHandler.level = FINE
4host-manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
4host-manager.org.apache.juli.AsyncFileHandler.prefix = host-manager.
4host-manager.org.apache.juli.AsyncFileHandler.encoding = UTF-8
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
java.util.logging.ConsoleHandler.encoding = UTF-8
############################################################
......
tomcat8 (8.5.37-1) unstable; urgency=medium
* Team upload.
* New upstream release
- Refreshed the patches
-- Emmanuel Bourg <ebourg@apache.org> Wed, 19 Dec 2018 21:53:00 +0100
tomcat8 (8.5.35-3) unstable; urgency=medium
* Team upload.
......
......@@ -9,7 +9,7 @@ Bug-Debian: http://bugs.debian.org/585379
Forwarded: not-needed
--- a/bin/catalina.sh
+++ b/bin/catalina.sh
@@ -356,7 +356,7 @@
@@ -364,7 +364,7 @@
-classpath "$CLASSPATH" \
-sourcepath "$CATALINA_HOME"/../../java \
-Djava.security.manager \
......@@ -18,7 +18,7 @@ Forwarded: not-needed
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
@@ -385,7 +385,7 @@
@@ -393,7 +393,7 @@
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......@@ -27,7 +27,7 @@ Forwarded: not-needed
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
@@ -453,7 +453,7 @@
@@ -471,7 +471,7 @@
-D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
-classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
......
......@@ -27,6 +27,7 @@ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ReadListener;
......@@ -222,17 +223,23 @@ public class InputBuffer extends Reader
public int available() {
int available = availableInThisBuffer();
if (available == 0) {
coyoteRequest.action(ActionCode.AVAILABLE,
Boolean.valueOf(coyoteRequest.getReadListener() != null));
available = (coyoteRequest.getAvailable() > 0) ? 1 : 0;
}
return available;
}
private int availableInThisBuffer() {
int available = 0;
if (state == BYTE_STATE) {
available = bb.remaining();
} else if (state == CHAR_STATE) {
available = cb.remaining();
}
if (available == 0) {
coyoteRequest.action(ActionCode.AVAILABLE,
Boolean.valueOf(coyoteRequest.getReadListener() != null));
available = (coyoteRequest.getAvailable() > 0) ? 1 : 0;
}
return available;
}
......@@ -290,11 +297,21 @@ public class InputBuffer extends Reader
}
return false;
}
boolean result = available() > 0;
if (!result) {
coyoteRequest.action(ActionCode.NB_READ_INTEREST, null);
// Checking for available data at the network level and registering for
// read can be done sequentially for HTTP/1.x and AJP as there is only
// ever a single thread processing the socket at any one time. However,
// for HTTP/2 there is one thread processing the connection and separate
// threads for each stream. For HTTP/2 the two operations have to be
// performed atomically else it is possible for the connection thread to
// read more data in to the buffer after the stream thread checks for
// available network data but before it registers for read.
if (availableInThisBuffer() > 0) {
return true;
}
return result;
AtomicBoolean result = new AtomicBoolean();
coyoteRequest.action(ActionCode.NB_READ_INTEREST, result);
return result.get();
}
......
......@@ -452,8 +452,6 @@ public class ApplicationContext implements org.apache.catalina.servlet4preview.S
uri = URLEncoder.DEFAULT.encode(getContextPath() + uri, StandardCharsets.UTF_8);
}
pos = normalizedUri.length();
// Use the thread local URI and mapping data
DispatchData dd = dispatchData.get();
if (dd == null) {
......
......@@ -197,29 +197,7 @@ public class ApplicationSessionCookieConfig implements SessionCookieConfig {
cookie.setHttpOnly(true);
}
String contextPath = context.getSessionCookiePath();
if (contextPath == null || contextPath.length() == 0) {
contextPath = scc.getPath();
}
if (contextPath == null || contextPath.length() == 0) {
contextPath = context.getEncodedPath();
}
if (context.getSessionCookiePathUsesTrailingSlash()) {
// Handle special case of ROOT context where cookies require a path of
// '/' but the servlet spec uses an empty string
// Also ensure the cookies for a context with a path of /foo don't get
// sent for requests with a path of /foobar
if (!contextPath.endsWith("/")) {
contextPath = contextPath + "/";
}
} else {
// Only handle special case of ROOT context where cookies require a
// path of '/' but the servlet spec uses an empty string
if (contextPath.length() == 0) {
contextPath = "/";
}
}
cookie.setPath(contextPath);
cookie.setPath(SessionConfig.getSessionCookiePath(context));
return cookie;
}
......
......@@ -68,7 +68,7 @@ public class AprLifecycleListener
protected static final int TCN_REQUIRED_MINOR = 2;
protected static final int TCN_REQUIRED_PATCH = 14;
protected static final int TCN_RECOMMENDED_MINOR = 2;
protected static final int TCN_RECOMMENDED_PV = 18;
protected static final int TCN_RECOMMENDED_PV = 19;
// ---------------------------------------------- Properties
......
......@@ -757,6 +757,12 @@ public class StandardContext extends ContainerBase
*/
private boolean clearReferencesObjectStreamClassCaches = true;
/**
* Should Tomcat attempt to clear references to classes loaded by this class
* loader from ThreadLocals?
*/
private boolean clearReferencesThreadLocals = true;
/**
* Should the effective web.xml be logged when the context starts?
*/
......@@ -2744,6 +2750,20 @@ public class StandardContext extends ContainerBase
}
public boolean getClearReferencesThreadLocals() {
return clearReferencesThreadLocals;
}
public void setClearReferencesThreadLocals(boolean clearReferencesThreadLocals) {
boolean oldClearReferencesThreadLocals = this.clearReferencesThreadLocals;
this.clearReferencesThreadLocals = clearReferencesThreadLocals;
support.firePropertyChange("clearReferencesThreadLocals",
oldClearReferencesThreadLocals,
this.clearReferencesThreadLocals);
}
public Boolean getFailCtxIfServletStartFails() {
return failCtxIfServletStartFails;
}
......@@ -5116,6 +5136,8 @@ public class StandardContext extends ContainerBase
getClearReferencesHttpClientKeepAliveThread());
setClassLoaderProperty("clearReferencesObjectStreamClassCaches",
getClearReferencesObjectStreamClassCaches());
setClassLoaderProperty("clearReferencesThreadLocals",
getClearReferencesThreadLocals());
// By calling unbindThread and bindThread in a row, we setup the
// current Thread CCL to be the webapp classloader
......
......@@ -94,6 +94,10 @@
description="Should Tomcat attempt to terminate TimerThreads that have been started by the web application? Advisable to be used only in a development environment."
type="boolean"/>
<attribute name="clearReferencesThreadLocals"
description="Should Tomcat attempt to clear ThreadLocal variables that have been populated with classes loaded by the web application?"
type="boolean"/>
<attribute name="configFile"
description="Location of the context.xml resource or file"
type="java.net.URL"/>
......
......@@ -81,7 +81,7 @@ import org.apache.juli.logging.LogFactory;
* <li>otherwise, the ip/host is declared to be the remote ip and looping is stopped.</li>
* </ul>
* </li>
* <li>If the request http header named <code>$protocolHeader</code> (e.g. <code>x-forwarded-for</code>) equals to the value of
* <li>If the request http header named <code>$protocolHeader</code> (e.g. <code>x-forwarded-proto</code>) consists only of forwards that match
* <code>protocolHeaderHttpsValue</code> configuration parameter (default <code>https</code>) then <code>request.isSecure = true</code>,
* <code>request.scheme = https</code> and <code>request.serverPort = 443</code>. Note that 443 can be overwritten with the
* <code>$httpsServerPort</code> configuration parameter.</li>
......@@ -847,8 +847,9 @@ public class RemoteIpFilter implements Filter {
if (protocolHeader != null) {
String protocolHeaderValue = request.getHeader(protocolHeader);
if (protocolHeaderValue == null) {
// don't modify the secure,scheme and serverPort attributes of the request
} else if (protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue)) {
// Don't modify the secure, scheme and serverPort attributes
// of the request
} else if (isForwardedProtoHeaderValueSecure(protocolHeaderValue)) {
xRequest.setSecure(true);
xRequest.setScheme("https");
setPorts(xRequest, httpsServerPort);
......@@ -892,6 +893,26 @@ public class RemoteIpFilter implements Filter {
}
/*
* Considers the value to be secure if it exclusively holds forwards for
* {@link #protocolHeaderHttpsValue}.
*/
private boolean isForwardedProtoHeaderValueSecure(String protocolHeaderValue) {
if (!protocolHeaderValue.contains(",")) {
return protocolHeaderHttpsValue.equalsIgnoreCase(protocolHeaderValue);
}
String[] forwardedProtocols = commaDelimitedListToStringArray(protocolHeaderValue);
if (forwardedProtocols.length == 0) {
return false;
}
for (int i = 0; i < forwardedProtocols.length; i++) {
if (!protocolHeaderHttpsValue.equalsIgnoreCase(forwardedProtocols[i])) {
return false;
}
}
return true;
}
private void setPorts(XForwardedRequest xrequest, int defaultPort) {
int port = defaultPort;
if (getPortHeader() != null) {
......
......@@ -377,6 +377,12 @@ public abstract class WebappClassLoaderBase extends URLClassLoader
*/
private boolean clearReferencesObjectStreamClassCaches = true;
/**
* Should Tomcat attempt to clear references to classes loaded by this class
* loader from ThreadLocals?
*/
private boolean clearReferencesThreadLocals = true;
/**
* Holds the class file transformers decorating this class loader. The
* CopyOnWriteArrayList is thread safe. It is expensive on writes, but
......@@ -625,6 +631,16 @@ public abstract class WebappClassLoaderBase extends URLClassLoader
}
public boolean getClearReferencesThreadLocals() {
return clearReferencesThreadLocals;
}
public void setClearReferencesThreadLocals(boolean clearReferencesThreadLocals) {
this.clearReferencesThreadLocals = clearReferencesThreadLocals;
}
// ------------------------------------------------------- Reloader Methods
/**
......@@ -1574,7 +1590,9 @@ public abstract class WebappClassLoaderBase extends URLClassLoader
}
// Check for leaks triggered by ThreadLocals loaded by this class loader
if (clearReferencesThreadLocals) {
checkThreadLocalsForLeaks();
}
// Clear RMI Targets loaded by this class loader
if (clearReferencesRmiTargets) {
......
......@@ -119,11 +119,16 @@ public class StatusManagerServlet
onStr = "*:type=ThreadPool,*";
objectName = new ObjectName(onStr);
set = mBeanServer.queryMBeans(objectName, null);
onStr = "*:type=ThreadPool,*,subType=SocketProperties";
objectName = new ObjectName(onStr);
Set<ObjectInstance> set2 = mBeanServer.queryMBeans(objectName, null);
iterator = set.iterator();
while (iterator.hasNext()) {
ObjectInstance oi = iterator.next();
if (!set2.contains(oi)) {
threadPools.addElement(oi.getObjectName());
}
}
// Query Global Request Processors
onStr = "*:type=GlobalRequestProcessor,*";
......
......@@ -306,13 +306,8 @@ public class StatusTransformer {
writer.print(mBeanServer.getAttribute(tpName, "currentThreadCount"));
writer.print(" " + args[2]);
writer.print(mBeanServer.getAttribute(tpName, "currentThreadsBusy"));
try {
Object value = mBeanServer.getAttribute(tpName, "keepAliveCount");
writer.print(" " + args[3]);
writer.print(value);
} catch (Exception e) {
// Ignore
}
writer.print(mBeanServer.getAttribute(tpName, "keepAliveCount"));
writer.print("<br>");
......
......@@ -1019,6 +1019,9 @@ public final class Mapper {
char[] buf = path.getBuffer();
if (contextVersion.resources != null && buf[pathEnd -1 ] != '/') {
String pathStr = path.toString();
// Note: Check redirect first to save unnecessary getResource()
// call. See BZ 62968.
if (contextVersion.object.getMapperDirectoryRedirectEnabled()) {
WebResource file;
// Handle context root
if (pathStr.length() == 0) {
......@@ -1026,8 +1029,7 @@ public final class Mapper {
} else {
file = contextVersion.resources.getResource(pathStr);
}
if (file != null && file.isDirectory() &&
contextVersion.object.getMapperDirectoryRedirectEnabled()) {
if (file != null && file.isDirectory()) {
// Note: this mutates the path: do not do any processing
// after this (since we set the redirectPath, there
// shouldn't be any)
......@@ -1039,6 +1041,10 @@ public final class Mapper {
mappingData.requestPath.setString(pathStr);
mappingData.wrapperPath.setString(pathStr);
}
} else {
mappingData.requestPath.setString(pathStr);
mappingData.wrapperPath.setString(pathStr);
}
}
}
......
......@@ -382,7 +382,7 @@ public final class CGIServlet extends HttpServlet {
if (getServletConfig().getInitParameter("cgiMethods") != null) {
String paramValue = getServletConfig().getInitParameter("cgiMethods");
paramValue.trim();
paramValue = paramValue.trim();
if ("*".equals(paramValue)) {
cgiMethodsAll = true;
} else {
......
......@@ -946,8 +946,11 @@ public class DefaultServlet extends HttpServlet {
if (debug > 0)
log("DefaultServlet.serveFile: contentType='" +
contentType + "'");
// Don't override a previously set content type
if (response.getContentType() == null) {
response.setContentType(contentType);
}
}
if (resource.isFile() && contentLength >= 0 &&
(!serveContent || ostream != null)) {
if (debug > 0)
......
......@@ -1130,36 +1130,8 @@ public class ContextConfig implements LifecycleListener {
}
if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
// Step 4. Process /WEB-INF/classes for annotations and
// @HandlesTypes matches
Map<String,JavaClassCacheEntry> javaClassCache = new HashMap<>();
if (ok) {
WebResource[] webResources =
context.getResources().listResources("/WEB-INF/classes");
for (WebResource webResource : webResources) {
// Skip the META-INF directory from any JARs that have been
// expanded in to WEB-INF/classes (sometimes IDEs do this).
if ("META-INF".equals(webResource.getName())) {
continue;
}
processAnnotationsWebResource(webResource, webXml,
webXml.isMetadataComplete(), javaClassCache);
}
}
// Step 5. Process JARs for annotations and
// @HandlesTypes matches - only need to process those fragments we
// are going to use (remember orderedFragments includes any
// container fragments)
if (ok) {
processAnnotations(
orderedFragments, webXml.isMetadataComplete(), javaClassCache);
}
// Cache, if used, is no longer required so clear it
javaClassCache.clear();
// Steps 4 & 5.
processClasses(webXml, orderedFragments);
}
if (!webXml.isMetadataComplete()) {
......@@ -1230,6 +1202,40 @@ public class ContextConfig implements LifecycleListener {
}
protected void processClasses(WebXml webXml, Set<WebXml> orderedFragments) {
// Step 4. Process /WEB-INF/classes for annotations and
// @HandlesTypes matches
Map<String, JavaClassCacheEntry> javaClassCache = new HashMap<>();
if (ok) {
WebResource[] webResources =
context.getResources().listResources("/WEB-INF/classes");
for (WebResource webResource : webResources) {
// Skip the META-INF directory from any JARs that have been
// expanded in to WEB-INF/classes (sometimes IDEs do this).
if ("META-INF".equals(webResource.getName())) {
continue;
}
processAnnotationsWebResource(webResource, webXml,
webXml.isMetadataComplete(), javaClassCache);
}
}
// Step 5. Process JARs for annotations and
// @HandlesTypes matches - only need to process those fragments we
// are going to use (remember orderedFragments includes any
// container fragments)
if (ok) {
processAnnotations(
orderedFragments, webXml.isMetadataComplete(), javaClassCache);
}
// Cache, if used, is no longer required so clear it
javaClassCache.clear();
}
private void configureContext(WebXml webxml) {
// As far as possible, process in alphabetical order so it is easy to
// check everything is present
......@@ -2051,6 +2057,11 @@ public class ContextConfig implements LifecycleListener {
return;
}
processClass(fragment, clazz);
}
protected void processClass(WebXml fragment, JavaClass clazz) {
AnnotationEntry[] annotationsEntries = clazz.getAnnotationEntries();
if (annotationsEntries != null) {
String className = clazz.getClassName();
......@@ -2069,6 +2080,7 @@ public class ContextConfig implements LifecycleListener {
}
}
/**
* For classes packaged with the web application, the class and each
* super class needs to be checked for a match with {@link HandlesTypes} or
......