1919import java .io .File ;
2020import java .io .IOException ;
2121import java .lang .reflect .AccessibleObject ;
22+ import java .lang .reflect .InvocationTargetException ;
23+ import java .lang .reflect .Method ;
2224import java .net .URL ;
2325import java .net .URLConnection ;
2426import java .util .Deque ;
2527import java .util .jar .JarFile ;
2628
29+ import javax .net .ssl .SSLEngine ;
30+ import javax .net .ssl .SSLParameters ;
31+
32+ import org .apache .tomcat .util .res .StringManager ;
33+
2734/**
2835 * This is the base implementation class for JRE compatibility and provides an
2936 * implementation based on Java 8. Sub-classes may extend this class and provide
@@ -37,6 +44,10 @@ public class JreCompat {
3744 private static final boolean graalAvailable ;
3845 private static final boolean jre11Available ;
3946 private static final boolean jre9Available ;
47+ private static final StringManager sm = StringManager .getManager (JreCompat .class );
48+
49+ protected static final Method setApplicationProtocolsMethod ;
50+ protected static final Method getApplicationProtocolMethod ;
4051
4152 static {
4253 // This is Tomcat 9 with a minimum Java version of Java 8.
@@ -55,6 +66,17 @@ public class JreCompat {
5566 jre9Available = false ;
5667 }
5768 jre11Available = instance .jarFileRuntimeMajorVersion () >= 11 ;
69+
70+ Method m1 = null ;
71+ Method m2 = null ;
72+ try {
73+ m1 = SSLParameters .class .getMethod ("setApplicationProtocols" , String [].class );
74+ m2 = SSLEngine .class .getMethod ("getApplicationProtocol" );
75+ } catch (ReflectiveOperationException | IllegalArgumentException e ) {
76+ // Only the newest Java 8 have the ALPN API, so ignore
77+ }
78+ setApplicationProtocolsMethod = m1 ;
79+ getApplicationProtocolMethod = m2 ;
5880 }
5981
6082
@@ -68,6 +90,11 @@ public static boolean isGraalAvailable() {
6890 }
6991
7092
93+ public static boolean isAlpnSupported () {
94+ return setApplicationProtocolsMethod != null && getApplicationProtocolMethod != null ;
95+ }
96+
97+
7198 public static boolean isJre9Available () {
7299 return jre9Available ;
73100 }
@@ -95,6 +122,48 @@ public boolean isInstanceOfInaccessibleObjectException(Throwable t) {
95122 }
96123
97124
125+ /**
126+ * Set the application protocols the server will accept for ALPN
127+ *
128+ * @param sslParameters The SSL parameters for a connection
129+ * @param protocols The application protocols to be allowed for that
130+ * connection
131+ */
132+ public void setApplicationProtocols (SSLParameters sslParameters , String [] protocols ) {
133+ if (setApplicationProtocolsMethod != null ) {
134+ try {
135+ setApplicationProtocolsMethod .invoke (sslParameters , (Object ) protocols );
136+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e ) {
137+ throw new UnsupportedOperationException (e );
138+ }
139+ } else {
140+ throw new UnsupportedOperationException (sm .getString ("jreCompat.noApplicationProtocols" ));
141+ }
142+ }
143+
144+
145+ /**
146+ * Get the application protocol that has been negotiated for connection
147+ * associated with the given SSLEngine.
148+ *
149+ * @param sslEngine The SSLEngine for which to obtain the negotiated
150+ * protocol
151+ *
152+ * @return The name of the negotiated protocol
153+ */
154+ public String getApplicationProtocol (SSLEngine sslEngine ) {
155+ if (getApplicationProtocolMethod != null ) {
156+ try {
157+ return (String ) getApplicationProtocolMethod .invoke (sslEngine );
158+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e ) {
159+ throw new UnsupportedOperationException (e );
160+ }
161+ } else {
162+ throw new UnsupportedOperationException (sm .getString ("jreCompat.noApplicationProtocol" ));
163+ }
164+ }
165+
166+
98167 /**
99168 * Disables caching for JAR URL connections. For Java 8 and earlier, this also disables
100169 * caching for ALL URL connections.
0 commit comments