Skip to content
Commits on Source (2)
......@@ -84,7 +84,7 @@ Download Page. There is one such page for every major Tomcat version:
If you have chosen to attach a patch to the Bugzilla issue (or email
one), then you'll need to download the sources as noted above, make your
desired changes and then manually generate your patch using diff (other
desired changes and then manually generate your patch using diff (or any
other tool).
##### GitHub
......
......@@ -38,7 +38,7 @@ CONTENTS:
===================
Dependency Changes:
===================
Tomcat @VERSION_MAJOR_MINOR@ is designed to run on Java SE 8 and later.
Tomcat @VERSION_MAJOR_MINOR@ is designed to run on Java @MIN_JAVA_VERSION@ and later.
==============
......
......@@ -157,7 +157,7 @@ create the following script file:
On Windows, %CATALINA_BASE%\bin\setenv.bat:
set "JRE_HOME=%ProgramFiles%\Java\jre8"
set "JRE_HOME=%ProgramFiles%\Java\jre@MIN_JAVA_VERSION@"
exit /b 0
On *nix, $CATALINA_BASE/bin/setenv.sh:
......
......@@ -17,6 +17,9 @@ rem limitations under the License.
rem ---------------------------------------------------------------------------
rem Start/Stop Script for the CATALINA Server
rem
rem For supported commands call "catalina.bat help" or see the usage section
rem towards the end of this file.
rem
rem Environment Variable Prerequisites
rem
rem Do not set the variables in this script. Instead put them into a script
......@@ -28,9 +31,8 @@ rem script will have no effect at all on Windows Services. As such, any
rem local customizations made in a CATALINA_BASE/bin/setenv.bat script
rem will also have no effect on Tomcat when launched as a Windows Service.
rem The configuration that controls Windows Services is stored in the Windows
rem Registry, and is most conveniently maintained using the "tomcatXw.exe"
rem maintenance utility, where "X" is the major version of Tomcat you are
rem running.
rem Registry, and is most conveniently maintained using the "tomcat@VERSION_MAJOR@w.exe"
rem maintenance utility.
rem
rem CATALINA_HOME May point at your Catalina "build" directory.
rem
......@@ -204,7 +206,7 @@ set "CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\bin\tomcat-juli.jar"
:juliClasspathDone
if not "%JSSE_OPTS%" == "" goto gotJsseOpts
set JSSE_OPTS="-Djdk.tls.ephemeralDHKeySize=2048"
set "JSSE_OPTS=-Djdk.tls.ephemeralDHKeySize=2048"
:gotJsseOpts
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
......
......@@ -18,6 +18,9 @@
# -----------------------------------------------------------------------------
# Control Script for the CATALINA Server
#
# For supported commands call "catalina.sh help" or see the usage section at
# the end of this file.
#
# Environment Variable Prerequisites
#
# Do not set the variables in this script. Instead put them into a script
......
......@@ -210,7 +210,7 @@ if exist "%CATALINA_HOME%\bin\%DEFAULT_SERVICE_NAME%.exe" (
"%EXECUTABLE%" //IS//%SERVICE_NAME% ^
--Description "Apache Tomcat @VERSION@ Server - https://tomcat.apache.org/" ^
--DisplayName "%DISPLAYNAME%" ^
--DisplayName "Apache Tomcat @VERSION_MAJOR_MINOR@ %SERVICE_NAME%" ^
--Install "%EXECUTABLE%" ^
--LogPath "%CATALINA_BASE%\logs" ^
--StdOutput auto ^
......
......@@ -25,10 +25,13 @@
# ----- Version Control Flags -----
version.major=9
version.minor=0
version.build=24
version.build=27
version.patch=0
version.suffix=
# ----- Source control flags -----
git.branch=master
# ----- Build control flags -----
# Note enabling validation uses Checkstyle which is LGPL licensed
ant.version.required=1.9.8
......@@ -126,15 +129,15 @@ wsdl4j-lib.loc=${base-maven.loc}/wsdl4j/wsdl4j/${wsdl4j-lib.version}/wsdl4j-${ws
# ----- Eclipse JDT, version 4.7 or later -----#
# See https://cwiki.apache.org/confluence/display/TOMCAT/Managing+Tomcat%27s+Dependency+on+the+Eclipse+JDT+Core+Batch+Compiler
#
# Checksum is from "SHA512 Checksums for 4.10" link at
# http://download.eclipse.org/eclipse/downloads/drops4/R-4.10-201812060815/
# http://download.eclipse.org/eclipse/downloads/drops4/R-4.10-201812060815/checksum/eclipse-4.10-SUMSSHA512
# Checksum is from "SHA512 Checksums for 4.13" link at
# http://download.eclipse.org/eclipse/downloads/drops4/R-4.13-201909161045/
# http://download.eclipse.org/eclipse/downloads/drops4/R-4.13-201909161045/checksum/eclipse-4.13-SUMSSHA512
#
jdt.version=4.12
jdt.release=R-4.12-201906051800/
jdt.version=4.13
jdt.release=R-4.13-201909161045/
jdt.checksum.enabled=true
jdt.checksum.algorithm=SHA-512
jdt.checksum.value=7d38921ae374a5112e7ed5596d85955b608ddf74849373d7a74b199961514807e749d8c8cad89871fa1fdd5e14bc6ec471665546a9f8d313da5c963589c307b0
jdt.checksum.value=d608e4b7fc9b061e327ad5c39112c032e310a48c57ddd01c9349f2be8f5ce4d3d0c3862b6b5cc105220a06a6dd62c477de654b9fbe6f4c8a3d3de816e5de19f7
jdt.home=${base.path}/ecj-${jdt.version}
jdt.jar=${jdt.home}/ecj-${jdt.version}.jar
# The download will be moved to the archive area eventually. We are taking care of that in advance.
......@@ -172,20 +175,20 @@ nsis.nsdialogs.dll=${nsis.home}/Plugins/${nsis.arch.dir}nsDialogs.dll
nsis.loc=${base-sf.loc}/nsis/nsis-${nsis.version}.zip
# ----- Commons Daemon, version 1.2.0 or later -----
commons-daemon.version=1.2.0
commons-daemon.version=1.2.2
# checksum for commons-daemon-1.2.0-bin.tar.gz
# checksum for commons-daemon-1.2.1-bin.tar.gz
commons-daemon.bin.checksum.enabled=true
commons-daemon.bin.checksum.algorithm=SHA-512
commons-daemon.bin.checksum.value=81fbbd1115d735232bbcc426d958bd8fe149c97bfe96df1549a19332afd4954f3f75c3a693f214bfef065931a1d79c528dfb2cefb1bb3628d211e1761814c23b
commons-daemon.bin.checksum.value=f9fb917aaf398f61c42796eb4168664e076f81bc3fae82790eb39c723f03a1e7cbc2304161938d8d8993b7fbb718214b94740dbf9679f6ef93e85b5a2e861761
# checksums for commons-daemon-1.1.0-native-src.tar.gz, commons-daemon-1.2.0-bin-windows.zip
# checksums for commons-daemon-1.2.1-native-src.tar.gz, commons-daemon-1.2.1-bin-windows.zip
commons-daemon.native.src.checksum.enabled=true
commons-daemon.native.src.checksum.algorithm=SHA-512
commons-daemon.native.src.checksum.value=c37f506b129b8a0efface6745dcc6d0d9d3e2663d28eca0df9903301f0b9b65fd8306e361935887fb459daf0a29da6fa63ea60f742ce4e497dc53a2a2d86db12
commons-daemon.native.src.checksum.value=45ad856a8a6b024e80905cfac5a741a57ab86479ecd65adab9641f5444d3a2362bb13d1ea38ec3db5eb89d30c29f2f6d3b0e48cbf2f60c081c4df2451acd1ab4
commons-daemon.native.win.checksum.enabled=true
commons-daemon.native.win.checksum.algorithm=SHA-512
commons-daemon.native.win.checksum.value=8b6e0bb4172861338e0cb3238f6da715c3cef04a88e8bfab0cbb487ef638aa69fd34de9407b0b2ed54451fbbcbff8a999324289052a581a5d07d6f6ff84a83b6
commons-daemon.native.win.checksum.value=16e7a6fc5bc83ada3bcf9e10cc69ef21400dc019d1f2be00caec0bce72c3bc5a7c72116878e12b4851a15bb473c0948a9c14e1a86b6addcefa6c20638dbcc88c
commons-daemon.home=${base.path}/commons-daemon-${commons-daemon.version}
commons-daemon.jar=${commons-daemon.home}/commons-daemon-${commons-daemon.version}.jar
......@@ -287,7 +290,7 @@ saaj-api.loc=${base-maven.loc}/javax/xml/soap/saaj-api/${saaj-api.version}/saaj-
# ----- provides OSGI metadata for JARs -----
bnd.version=4.2.0
# checksums for biz.aQute.bnd-4.0.0.jar, biz.aQute.bndlib-4.0.0.jar
# checksums for biz.aQute.bnd-4.2.0.jar, biz.aQute.bndlib-4.2.0.jar
bnd.checksum.enabled=true
bnd.checksum.algorithm=MD5|SHA-1
bnd.checksum.value=ca26a671ea67bf75d83b1588bdd68923|d4bc96b2619f95e596bbf3f725f3b077e96c5d43
......
......@@ -90,10 +90,11 @@
<!-- build output directory for jdbc-pool -->
<property name="tomcat.pool" value="${tomcat.output}/jdbc-pool"/>
<!-- Servlet 4.0 spec requires 1.8+ -->
<property name="compile.source" value="1.8"/>
<property name="compile.target" value="1.8"/>
<!-- Servlet 4.0 spec requires Java 8+ -->
<property name="compile.source" value="8"/>
<property name="compile.target" value="8"/>
<property name="compile.release" value="8"/>
<property name="min.java.version" value="8"/>
<!-- Locations to create the JAR artifacts -->
<!-- Standard JARs -->
......@@ -196,9 +197,9 @@
<!-- Java 9 -->
<available classname="java.lang.reflect.InaccessibleObjectException"
property="java9.add.modules"
value="--add-modules java.xml.ws"/>
<property name="java9.add.modules" value=""/>
property="java9.javadoc.options"
value="-html5"/>
<property name="java9.javadoc.options" value=""/>
<!-- Classpaths -->
<path id="compile.classpath">
......@@ -239,6 +240,8 @@
<filter token="VERSION_MAJOR_MINOR" value="${version.major.minor}"/>
<filter token="VERSION_BUILT" value="${today} ${tstamp} UTC"/>
<filter token="JDT_VERSION" value="${jdt.version}"/>
<filter token="GIT_BRANCH" value="${git.branch}"/>
<filter token="MIN_JAVA_VERSION" value="${min.java.version}"/>
</filterset>
<!-- Files to change line endings for depending on target platform -->
......@@ -595,8 +598,9 @@
<fileset dir="modules/jdbc-pool" >
<exclude name=".*/**"/>
<exclude name="**/MANIFEST.MF"/>
<exclude name="build.properties" />
<patternset refid="text.files" />
<!-- Exclude developer specific local files -->
<exclude name="build.properties" />
</fileset>
</checkstyle>
<!-- javax package checks -->
......@@ -1840,6 +1844,27 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
<target name="javadoc" depends="dist-source"
description="Create the Tomcat javadoc" >
<javadoc packagenames="javax.annotation.*"
sourcepath="${tomcat.dist}/src/java"
destdir="${tomcat.dist}/webapps/docs/annotationapi"
version="true"
windowtitle="Common Annotations 1.3 API Documentation - Apache Tomcat ${version}"
doctitle="Common Annotations 1.3 API - Apache Tomcat ${version}"
header="&lt;b&gt;Common Annotations 1.3 - Apache Tomcat ${version}&lt;/b&gt;"
bottom="Copyright &amp;#169; 2000-${year} Apache Software Foundation. All Rights Reserved."
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
<classpath>
<path refid="compile.classpath"/>
<path location="${ant.core.lib}"/>
</classpath>
</javadoc>
<javadoc packagenames="javax.servlet.*"
excludepackagenames="javax.servlet.jsp.*"
sourcepath="${tomcat.dist}/src/java"
......@@ -1852,7 +1877,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
......@@ -1872,7 +1898,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
......@@ -1892,7 +1919,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
......@@ -1912,6 +1940,27 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
<classpath>
<path refid="compile.classpath"/>
<path location="${ant.core.lib}"/>
</classpath>
</javadoc>
<javadoc packagenames="javax.security.auth.message.*"
sourcepath="${tomcat.dist}/src/java"
destdir="${tomcat.dist}/webapps/docs/jaspicapi"
version="true"
windowtitle="JASPIC 1.1 API Documentation - Apache Tomcat ${version}"
doctitle="JASPIC 1.1 API - Apache Tomcat ${version}"
header="&lt;b&gt;JASPIC 1.1 - Apache Tomcat ${version}&lt;/b&gt;"
bottom="Copyright &amp;#169; 2000-${year} Apache Software Foundation. All Rights Reserved."
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp"
maxmemory="512m"
failonerror="true"
......@@ -1931,7 +1980,8 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
encoding="UTF-8"
docencoding="UTF-8"
charset="UTF-8"
additionalparam="-breakiterator -notimestamp ${java9.add.modules}"
additionalparam="-breakiterator -notimestamp ${java9.javadoc.options}"
source="${compile.source}"
maxmemory="512m"
failonerror="true"
failonwarning="true">
......@@ -1939,12 +1989,13 @@ Apache Tomcat ${version} native binaries for Win64 AMD64/EMT64 platform.
<path refid="compile.classpath"/>
<path location="${ant.core.lib}"/>
</classpath>
<link href="../annotationapi"/>
<link href="../servletapi"/>
<link href="../jspapi"/>
<link href="../elapi"/>
<link href="../websocketapi"/>
<link href="http://docs.oracle.com/javase/8/docs/api/"/>
<link href="https://commons.apache.org/proper/commons-io/javadocs/api-release/"/>
<link href="../jaspicapi"/>
<link href="https://docs.oracle.com/javase/8/docs/api/"/>
<link href="https://javaee.github.io/javaee-spec/javadocs/"/>
<packageset dir="${tomcat.dist}/src/java/">
<include name="org/**"/>
......
......@@ -76,7 +76,7 @@
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the
......@@ -93,7 +93,7 @@
</SSLHostConfig>
</Connector>
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
......
......@@ -34,6 +34,8 @@ public @interface Resource {
public String name() default "";
/**
* Uses generics since Common Annotations 1.2.
*
* @return The type for instances of this resource
*/
public Class<?> type() default Object.class;
public AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
......@@ -42,6 +44,8 @@ public @interface Resource {
public String mappedName() default "";
/**
* @since Common Annotations 1.1
*
* @return The name of the entry, if any, to use for this resource
*/
public String lookup() default "";
}
......@@ -89,7 +89,7 @@ public class BeanELResolver extends ELResolver {
}
context.setPropertyResolved(base, property);
Method m = this.property(context, base, property).read(context);
Method m = this.property(context, base, property).read(context, base);
try {
return m.invoke(base, (Object[]) null);
} catch (InvocationTargetException e) {
......@@ -117,7 +117,7 @@ public class BeanELResolver extends ELResolver {
"resolverNotWriteable", base.getClass().getName()));
}
Method m = this.property(context, base, property).write(context);
Method m = this.property(context, base, property).write(context, base);
try {
m.invoke(base, value);
} catch (InvocationTargetException e) {
......@@ -147,7 +147,7 @@ public class BeanELResolver extends ELResolver {
// Find the matching method
Method matchingMethod =
Util.findMethod(base.getClass(), methodName, paramTypes, params);
Util.findMethod(base.getClass(), base, methodName, paramTypes, params);
Object[] parameters = Util.buildParameters(
matchingMethod.getParameterTypes(), matchingMethod.isVarArgs(),
......@@ -176,7 +176,7 @@ public class BeanELResolver extends ELResolver {
}
context.setPropertyResolved(base, property);
return this.readOnly || this.property(context, base, property).isReadOnly();
return this.readOnly || this.property(context, base, property).isReadOnly(base);
}
@Override
......@@ -263,10 +263,6 @@ public class BeanELResolver extends ELResolver {
return property;
}
public BeanProperty getBeanProperty(String name) {
return get(null, name);
}
private Class<?> getType() {
return type;
}
......@@ -289,28 +285,18 @@ public class BeanELResolver extends ELResolver {
this.type = descriptor.getPropertyType();
}
// Can't use Class<?> because API needs to match specification
@SuppressWarnings("rawtypes")
public Class getPropertyType() {
public Class<?> getPropertyType() {
return this.type;
}
public boolean isReadOnly() {
public boolean isReadOnly(Object base) {
return this.write == null &&
(null == (this.write = Util.getMethod(this.owner, descriptor.getWriteMethod())));
}
public Method getWriteMethod() {
return write(null);
}
public Method getReadMethod() {
return this.read(null);
(null == (this.write = Util.getMethod(this.owner, base, descriptor.getWriteMethod())));
}
private Method write(ELContext ctx) {
private Method write(ELContext ctx, Object base) {
if (this.write == null) {
this.write = Util.getMethod(this.owner, descriptor.getWriteMethod());
this.write = Util.getMethod(this.owner, base, descriptor.getWriteMethod());
if (this.write == null) {
throw new PropertyNotWritableException(Util.message(ctx,
"propertyNotWritable", new Object[] {
......@@ -320,9 +306,9 @@ public class BeanELResolver extends ELResolver {
return this.write;
}
private Method read(ELContext ctx) {
private Method read(ELContext ctx, Object base) {
if (this.read == null) {
this.read = Util.getMethod(this.owner, descriptor.getReadMethod());
this.read = Util.getMethod(this.owner, base, descriptor.getReadMethod());
if (this.read == null) {
throw new PropertyNotFoundException(Util.message(ctx,
"propertyNotReadable", new Object[] {
......
......@@ -109,11 +109,17 @@ public class ELProcessor {
function = sig.getName();
}
// Only returns public methods. Java 9+ access is checked below.
Method methods[] = clazz.getMethods();
JreCompat jreCompat = JreCompat.getInstance();
for (Method method : methods) {
if (!Modifier.isStatic(method.getModifiers())) {
continue;
}
if (!jreCompat.canAcccess(null, method)) {
continue;
}
if (method.getName().equals(sig.getName())) {
if (sig.getParamTypeNames() == null) {
// Only a name provided, no signature so map the first
......@@ -184,8 +190,9 @@ public class ELProcessor {
int modifiers = method.getModifiers();
// Check for public method as well as being static
if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
// Check for static, public method and module access for Java 9+
JreCompat jreCompat = JreCompat.getInstance();
if (!Modifier.isStatic(modifiers) || !jreCompat.canAcccess(null, method)) {
throw new NoSuchMethodException(Util.message(context,
"elProcessor.defineFunctionInvalidMethod", method.getName(),
method.getDeclaringClass().getName()));
......
......@@ -464,10 +464,12 @@ public class ImportHandler {
return null;
}
// Class must be public, non-abstract and not an interface
// Class must be public, non-abstract, not an interface and (for
// Java 9+) in an exported package
JreCompat jreCompat = JreCompat.getInstance();
int modifiers = clazz.getModifiers();
if (!Modifier.isPublic(modifiers) || Modifier.isAbstract(modifiers) ||
Modifier.isInterface(modifiers)) {
Modifier.isInterface(modifiers) || !jreCompat.isExported(clazz)) {
if (throwException) {
throw new ELException(Util.message(
null, "importHandler.invalidClass", name));
......
/*
* 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 javax.el;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
/*
* This is a cut down version of org.apache.tomcat.util.Jre9Compat that provides
* only the methods required by the EL implementation.
*
* This class is duplicated in org.apache.el.util
* When making changes keep the two in sync.
*/
class Jre9Compat extends JreCompat {
private static final Method canAccessMethod;
private static final Method getModuleMethod;
private static final Method isExportedMethod;
static {
Method m1 = null;
Method m2 = null;
Method m3 = null;
try {
m1 = AccessibleObject.class.getMethod("canAccess", Object.class);
m2 = Class.class.getMethod("getModule");
Class<?> moduleClass = Class.forName("java.lang.Module");
m3 = moduleClass.getMethod("isExported", String.class);
} catch (NoSuchMethodException e) {
// Expected for Java 8
} catch (ClassNotFoundException e) {
// Can't log this so...
throw new RuntimeException(e);
}
canAccessMethod = m1;
getModuleMethod = m2;
isExportedMethod = m3;
}
public static boolean isSupported() {
return canAccessMethod != null;
}
@Override
public boolean canAcccess(Object base, AccessibleObject accessibleObject) {
try {
return ((Boolean) canAccessMethod.invoke(accessibleObject, base)).booleanValue();
} catch (ReflectiveOperationException | IllegalArgumentException e) {
return false;
}
}
@Override
public boolean isExported(Class<?> type) {
try {
String packageName = type.getPackage().getName();
Object module = getModuleMethod.invoke(type);
return ((Boolean) isExportedMethod.invoke(module, packageName)).booleanValue();
} catch (ReflectiveOperationException e) {
return false;
}
}
}
/*
* 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 javax.el;
import java.lang.reflect.AccessibleObject;
/*
* This is cut down version of org.apache.tomcat.util.JreCompat that provides
* only the methods required by the EL implementation.
*
* This class is duplicated in org.apache.el.util
* When making changes keep the two in sync.
*/
class JreCompat {
private static final JreCompat instance;
static {
if (Jre9Compat.isSupported()) {
instance = new Jre9Compat();
} else {
instance = new JreCompat();
}
}
public static JreCompat getInstance() {
return instance;
}
/**
* Is the accessibleObject accessible (as a result of appropriate module
* exports) on the provided instance?
*
* @param base The specific instance to be tested.
* @param accessibleObject The method/field/constructor to be tested.
*
* @return {code true} if the AccessibleObject can be accessed otherwise
* {code false}
*/
public boolean canAcccess(Object base, AccessibleObject accessibleObject) {
// Java 8 doesn't support modules so default to true
return true;
}
/**
* Is the given class in an exported package?
*
* @param type The class to test
*
* @return Always {@code true} for Java 8. {@code true} if the enclosing
* package is exported for Java 9+
*/
public boolean isExported(Class<?> type) {
return true;
}
}
......@@ -29,7 +29,7 @@ expressionFactory.readFailed=Failed to read [{0}]
importHandler.ambiguousImport=The class [{0}] could not be imported as it conflicts with [{1}] which has already been imported
importHandler.ambiguousStaticImport=The static import [{0}] could not be processed as it conflicts with [{1}] which has already been imported
importHandler.classNotFound=The class [{0}] could not be imported as it could not be found
importHandler.invalidClass=The class [{0}] must be public, non-abstract and not an interface
importHandler.invalidClass=The class [{0}] must be public, non-abstract, not an interface and (for Java 9+) in an exported package
importHandler.invalidClassName=Name of class to import [{0}] must include a package
importHandler.invalidClassNameForStatic=The class [{0}] specified for static import [{1}] is not valid
importHandler.invalidStaticName=Name of static method or field to import [{0}] must include a class
......@@ -45,7 +45,7 @@ propertyReadError=Error reading [{1}] on type [{0}]
propertyWriteError=Error writing [{1}] on type [{0}]
staticFieldELResolver.methodNotFound=No matching public static method named [{0}] found on class [{1}]
staticFieldELResolver.notFound=No public static field named [{0}] was found on class [{1}]
staticFieldELResolver.notFound=No public static field named [{0}] was found on (exported for Java 9+) class [{1}]
staticFieldELResolver.notWriteable=Writing to static fields (in this case field [{0}] on class [{1}]) is not permitted
util.method.ambiguous=Unable to find unambiguous method: {0}.{1}({2})
......
......@@ -16,7 +16,7 @@
elProcessor.defineFunctionInvalidClass=Die Klasse [{0}] ist nicht öffentlich
elProcessor.defineFunctionInvalidMethod=Die Methode [{0}] der Klasse [{1}] ist nicht public static
expressionFactory.cannotFind=Kann die ExpressionFactory mit dem Typ ''[{0}]'' nicht finden
expressionFactory.cannotFind=Kann die ExpressionFactory mit dem Typ [{0}] nicht finden
importHandler.classNotFound=Die Klasse [{0}] konnte nicht importiert werden, da sie nicht gefunden werden konnte
importHandler.invalidClassNameForStatic=Ungültige Klasse [{0}] für angegebenen static import [{1}]
......@@ -43,8 +43,10 @@ public class StaticFieldELResolver extends ELResolver {
try {
Field field = clazz.getField(name);
int modifiers = field.getModifiers();
JreCompat jreCompat = JreCompat.getInstance();
if (Modifier.isStatic(modifiers) &&
Modifier.isPublic(modifiers)) {
Modifier.isPublic(modifiers) &&
jreCompat.canAcccess(null, field)) {
return field.get(null);
}
} catch (IllegalArgumentException | IllegalAccessException |
......@@ -111,11 +113,13 @@ public class StaticFieldELResolver extends ELResolver {
return result;
} else {
Method match =
Util.findMethod(clazz, methodName, paramTypes, params);
// Static method so base should be null
Method match = Util.findMethod(clazz, null, methodName, paramTypes, params);
int modifiers = match.getModifiers();
if (!Modifier.isStatic(modifiers)) {
// Note: On Java 9 and above, the isStatic check becomes
// unnecessary because the canAccess() call in Util.findMethod()
// effectively performs the same check
if (match == null || !Modifier.isStatic(match.getModifiers())) {
throw new MethodNotFoundException(Util.message(context,
"staticFieldELResolver.methodNotFound", methodName,
clazz.getName()));
......@@ -153,8 +157,10 @@ public class StaticFieldELResolver extends ELResolver {
try {
Field field = clazz.getField(name);
int modifiers = field.getModifiers();
JreCompat jreCompat = JreCompat.getInstance();
if (Modifier.isStatic(modifiers) &&
Modifier.isPublic(modifiers)) {
Modifier.isPublic(modifiers) &&
jreCompat.canAcccess(null, field)) {
return field.getType();
}
} catch (IllegalArgumentException | NoSuchFieldException |
......
......@@ -197,7 +197,7 @@ class Util {
* This method duplicates code in org.apache.el.util.ReflectionUtil. When
* making changes keep the code in sync.
*/
static Method findMethod(Class<?> clazz, String methodName,
static Method findMethod(Class<?> clazz, Object base, String methodName,
Class<?>[] paramTypes, Object[] paramValues) {
if (clazz == null || methodName == null) {
......@@ -212,11 +212,11 @@ class Util {
Method[] methods = clazz.getMethods();
List<Wrapper> wrappers = Wrapper.wrap(methods, methodName);
List<Wrapper<Method>> wrappers = Wrapper.wrap(methods, methodName);
Wrapper result = findWrapper(clazz, wrappers, methodName, paramTypes, paramValues);
Wrapper<Method> result = findWrapper(clazz, wrappers, methodName, paramTypes, paramValues);
return getMethod(clazz, (Method) result.unWrap());
return getMethod(clazz, base, result.unWrap());
}
/*
......@@ -224,14 +224,14 @@ class Util {
* making changes keep the code in sync.
*/
@SuppressWarnings("null")
private static Wrapper findWrapper(Class<?> clazz, List<Wrapper> wrappers,
private static <T> Wrapper<T> findWrapper(Class<?> clazz, List<Wrapper<T>> wrappers,
String name, Class<?>[] paramTypes, Object[] paramValues) {
Map<Wrapper,MatchResult> candidates = new HashMap<>();
Map<Wrapper<T>,MatchResult> candidates = new HashMap<>();
int paramCount = paramTypes.length;
for (Wrapper w : wrappers) {
for (Wrapper<T> w : wrappers) {
Class<?>[] mParamTypes = w.getParameterTypes();
int mParamCount;
if (mParamTypes == null) {
......@@ -336,9 +336,9 @@ class Util {
// Look for the method that has the highest number of parameters where
// the type matches exactly
MatchResult bestMatch = new MatchResult(0, 0, 0, false);
Wrapper match = null;
Wrapper<T> match = null;
boolean multiple = false;
for (Map.Entry<Wrapper, MatchResult> entry : candidates.entrySet()) {
for (Map.Entry<Wrapper<T>, MatchResult> entry : candidates.entrySet()) {
int cmp = entry.getValue().compareTo(bestMatch);
if (cmp > 0 || match == null) {
bestMatch = entry.getValue();
......@@ -400,10 +400,10 @@ class Util {
* This method duplicates code in org.apache.el.util.ReflectionUtil. When
* making changes keep the code in sync.
*/
private static Wrapper resolveAmbiguousWrapper(Set<Wrapper> candidates,
private static <T> Wrapper<T> resolveAmbiguousWrapper(Set<Wrapper<T>> candidates,
Class<?>[] paramTypes) {
// Identify which parameter isn't an exact match
Wrapper w = candidates.iterator().next();
Wrapper<T> w = candidates.iterator().next();
int nonMatchIndex = 0;
Class<?> nonMatchClass = null;
......@@ -421,7 +421,7 @@ class Util {
return null;
}
for (Wrapper c : candidates) {
for (Wrapper<T> c : candidates) {
if (c.getParameterTypes()[nonMatchIndex] ==
paramTypes[nonMatchIndex]) {
// Methods have different non-matching parameters
......@@ -433,7 +433,7 @@ class Util {
// Can't be null
Class<?> superClass = nonMatchClass.getSuperclass();
while (superClass != null) {
for (Wrapper c : candidates) {
for (Wrapper<T> c : candidates) {
if (c.getParameterTypes()[nonMatchIndex].equals(superClass)) {
// Found a match
return c;
......@@ -443,9 +443,9 @@ class Util {
}
// Treat instances of Number as a special case
Wrapper match = null;
Wrapper<T> match = null;
if (Number.class.isAssignableFrom(nonMatchClass)) {
for (Wrapper c : candidates) {
for (Wrapper<T> c : candidates) {
Class<?> candidateType = c.getParameterTypes()[nonMatchIndex];
if (Number.class.isAssignableFrom(candidateType) ||
candidateType.isPrimitive()) {
......@@ -539,8 +539,13 @@ class Util {
* This method duplicates code in org.apache.el.util.ReflectionUtil. When
* making changes keep the code in sync.
*/
static Method getMethod(Class<?> type, Method m) {
if (m == null || Modifier.isPublic(type.getModifiers())) {
static Method getMethod(Class<?> type, Object base, Method m) {
JreCompat jreCompat = JreCompat.getInstance();
// If base is null, method MUST be static
// If base is non-null, method may be static or non-static
if (m == null ||
(Modifier.isPublic(type.getModifiers()) &&
(jreCompat.canAcccess(base, m) || base != null && jreCompat.canAcccess(null, m)))) {
return m;
}
Class<?>[] inf = type.getInterfaces();
......@@ -548,7 +553,7 @@ class Util {
for (int i = 0; i < inf.length; i++) {
try {
mp = inf[i].getMethod(m.getName(), m.getParameterTypes());
mp = getMethod(mp.getDeclaringClass(), mp);
mp = getMethod(mp.getDeclaringClass(), base, mp);
if (mp != null) {
return mp;
}
......@@ -560,7 +565,7 @@ class Util {
if (sup != null) {
try {
mp = sup.getMethod(m.getName(), m.getParameterTypes());
mp = getMethod(mp.getDeclaringClass(), mp);
mp = getMethod(mp.getDeclaringClass(), base, mp);
if (mp != null) {
return mp;
}
......@@ -589,32 +594,20 @@ class Util {
Constructor<?>[] constructors = clazz.getConstructors();
List<Wrapper> wrappers = Wrapper.wrap(constructors);
List<Wrapper<Constructor<?>>> wrappers = Wrapper.wrap(constructors);
Wrapper result = findWrapper(clazz, wrappers, methodName, paramTypes, paramValues);
return getConstructor(clazz, (Constructor<?>) result.unWrap());
}
Wrapper<Constructor<?>> wrapper = findWrapper(clazz, wrappers, methodName, paramTypes, paramValues);
Constructor<?> constructor = wrapper.unWrap();
static Constructor<?> getConstructor(Class<?> type, Constructor<?> c) {
if (c == null || Modifier.isPublic(type.getModifiers())) {
return c;
}
Constructor<?> cp = null;
Class<?> sup = type.getSuperclass();
if (sup != null) {
try {
cp = sup.getConstructor(c.getParameterTypes());
cp = getConstructor(cp.getDeclaringClass(), cp);
if (cp != null) {
return cp;
}
} catch (NoSuchMethodException e) {
// Ignore
}
JreCompat jreCompat = JreCompat.getInstance();
if (!Modifier.isPublic(clazz.getModifiers()) || !jreCompat.canAcccess(null, constructor)) {
throw new MethodNotFoundException(message(
null, "util.method.notfound", clazz, methodName,
paramString(paramTypes)));
}
return null;
return constructor;
}
......@@ -672,10 +665,10 @@ class Util {
}
private abstract static class Wrapper {
private abstract static class Wrapper<T> {
public static List<Wrapper> wrap(Method[] methods, String name) {
List<Wrapper> result = new ArrayList<>();
public static List<Wrapper<Method>> wrap(Method[] methods, String name) {
List<Wrapper<Method>> result = new ArrayList<>();
for (Method method : methods) {
if (method.getName().equals(name)) {
result.add(new MethodWrapper(method));
......@@ -684,22 +677,22 @@ class Util {
return result;
}
public static List<Wrapper> wrap(Constructor<?>[] constructors) {
List<Wrapper> result = new ArrayList<>();
public static List<Wrapper<Constructor<?>>> wrap(Constructor<?>[] constructors) {
List<Wrapper<Constructor<?>>> result = new ArrayList<>();
for (Constructor<?> constructor : constructors) {
result.add(new ConstructorWrapper(constructor));
}
return result;
}
public abstract Object unWrap();
public abstract T unWrap();
public abstract Class<?>[] getParameterTypes();
public abstract boolean isVarArgs();
public abstract boolean isBridge();
}
private static class MethodWrapper extends Wrapper {
private static class MethodWrapper extends Wrapper<Method> {
private final Method m;
public MethodWrapper(Method m) {
......@@ -707,7 +700,7 @@ class Util {
}
@Override
public Object unWrap() {
public Method unWrap() {
return m;
}
......@@ -727,7 +720,7 @@ class Util {
}
}
private static class ConstructorWrapper extends Wrapper {
private static class ConstructorWrapper extends Wrapper<Constructor<?>> {
private final Constructor<?> c;
public ConstructorWrapper(Constructor<?> c) {
......@@ -735,7 +728,7 @@ class Util {
}
@Override
public Object unWrap() {
public Constructor<?> unWrap() {
return c;
}
......
......@@ -42,7 +42,7 @@ public interface ServletContextListener extends EventListener {
/**
** Notification that the servlet context is about to be shut down. All
* servlets and filters have been destroy()ed before any
* servlets and filters have been destroyed before any
* ServletContextListeners are notified of context destruction.
* The default implementation is a NO-OP.
* @param sce Information about the ServletContext that was destroyed
......