/** * Returns true if the method exists on the supplied {@code target}. */ public boolean isSupported(T target) { return getMethod(target.getClass()) != null; }
@Override public void configureTlsExtensions( SSLSocket sslSocket, String hostname, List<Protocol> protocols) { // Enable SNI and session tickets. if (hostname != null) { setUseSessionTickets.invokeOptionalWithoutCheckedException(sslSocket, true); setHostname.invokeOptionalWithoutCheckedException(sslSocket, hostname); } // Enable ALPN. if (setAlpnProtocols != null && setAlpnProtocols.isSupported(sslSocket)) { Object[] parameters = {concatLengthPrefixed(protocols)}; setAlpnProtocols.invokeWithoutCheckedException(sslSocket, parameters); } }
@Override public String getSelectedProtocol(SSLSocket socket) { if (getAlpnSelectedProtocol == null) return null; if (!getAlpnSelectedProtocol.isSupported(socket)) return null; byte[] alpnResult = (byte[]) getAlpnSelectedProtocol.invokeWithoutCheckedException(socket); return alpnResult != null ? new String(alpnResult, Util.UTF_8) : null; }
/** * Invokes the method on {@code target}. If the method does not exist or is not public then * {@code null} is returned. Any RuntimeException thrown by the method is thrown, checked * exceptions are wrapped in an {@link AssertionError}. * * @throws IllegalArgumentException if the arguments are invalid */ public Object invokeOptionalWithoutCheckedException(T target, Object... args) { try { return invokeOptional(target, args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } AssertionError error = new AssertionError("Unexpected exception"); error.initCause(targetException); throw error; } }
/** * Perform a lookup for the method. No caching. In order to return a method the method name and * arguments must match those specified when the {@link OptionalMethod} was created. If the return * type is specified (i.e. non-null) it must also be compatible. The method must also be public. */ private Method getMethod(Class<?> clazz) { Method method = null; if (methodName != null) { method = getPublicMethod(clazz, methodName, methodParams); if (method != null && returnType != null && !returnType.isAssignableFrom(method.getReturnType())) { // If the return type is non-null it must be compatible. method = null; } } return method; }
/** * Invokes the method on {@code target}. Throws an error if the method is not supported. Any * RuntimeException thrown by the method is thrown, checked exceptions are wrapped in an {@link * AssertionError}. * * @throws IllegalArgumentException if the arguments are invalid */ public Object invokeWithoutCheckedException(T target, Object... args) { try { return invoke(target, args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } AssertionError error = new AssertionError("Unexpected exception"); error.initCause(targetException); throw error; } }
public static Platform buildIfSupported() { // Attempt to find Android 2.3+ APIs. try { Class<?> sslParametersClass; try { sslParametersClass = Class.forName("com.android.org.conscrypt.SSLParametersImpl"); } catch (ClassNotFoundException e) { // Older platform before being unbundled. sslParametersClass = Class.forName( "org.apache.harmony.xnet.provider.jsse.SSLParametersImpl"); } OptionalMethod<Socket> setUseSessionTickets = new OptionalMethod<>( null, "setUseSessionTickets", boolean.class); OptionalMethod<Socket> setHostname = new OptionalMethod<>( null, "setHostname", String.class); OptionalMethod<Socket> getAlpnSelectedProtocol = null; OptionalMethod<Socket> setAlpnProtocols = null; if (supportsAlpn()) { getAlpnSelectedProtocol = new OptionalMethod<>(byte[].class, "getAlpnSelectedProtocol"); setAlpnProtocols = new OptionalMethod<>(null, "setAlpnProtocols", byte[].class); } return new AndroidPlatform(sslParametersClass, setUseSessionTickets, setHostname, getAlpnSelectedProtocol, setAlpnProtocols); } catch (ClassNotFoundException ignored) { // This isn't an Android runtime. } return null; }
@Override public @Nullable String getSelectedProtocol(SSLSocket socket) { if (getAlpnSelectedProtocol == null) return null; if (!getAlpnSelectedProtocol.isSupported(socket)) return null; byte[] alpnResult = (byte[]) getAlpnSelectedProtocol.invokeWithoutCheckedException(socket); return alpnResult != null ? new String(alpnResult, Util.UTF_8) : null; }
/** * Invokes the method on {@code target}. If the method does not exist or is not public then * {@code null} is returned. Any RuntimeException thrown by the method is thrown, checked * exceptions are wrapped in an {@link AssertionError}. * * @throws IllegalArgumentException if the arguments are invalid */ public Object invokeOptionalWithoutCheckedException(T target, Object... args) { try { return invokeOptional(target, args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } AssertionError error = new AssertionError("Unexpected exception"); error.initCause(targetException); throw error; } }
/** * Perform a lookup for the method. No caching. In order to return a method the method name and * arguments must match those specified when the {@link OptionalMethod} was created. If the return * type is specified (i.e. non-null) it must also be compatible. The method must also be public. */ private Method getMethod(Class<?> clazz) { Method method = null; if (methodName != null) { method = getPublicMethod(clazz, methodName, methodParams); if (method != null && returnType != null && !returnType.isAssignableFrom(method.getReturnType())) { // If the return type is non-null it must be compatible. method = null; } } return method; }
/** * Invokes the method on {@code target}. Throws an error if the method is not supported. Any * RuntimeException thrown by the method is thrown, checked exceptions are wrapped in an {@link * AssertionError}. * * @throws IllegalArgumentException if the arguments are invalid */ public Object invokeWithoutCheckedException(T target, Object... args) { try { return invoke(target, args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } AssertionError error = new AssertionError("Unexpected exception"); error.initCause(targetException); throw error; } }
public static Platform buildIfSupported() { // Attempt to find Android 2.3+ APIs. try { Class<?> sslParametersClass; try { sslParametersClass = Class.forName("com.android.org.conscrypt.SSLParametersImpl"); } catch (ClassNotFoundException e) { // Older platform before being unbundled. sslParametersClass = Class.forName( "org.apache.harmony.xnet.provider.jsse.SSLParametersImpl"); } OptionalMethod<Socket> setUseSessionTickets = new OptionalMethod<>( null, "setUseSessionTickets", boolean.class); OptionalMethod<Socket> setHostname = new OptionalMethod<>( null, "setHostname", String.class); OptionalMethod<Socket> getAlpnSelectedProtocol = null; OptionalMethod<Socket> setAlpnProtocols = null; if (supportsAlpn()) { getAlpnSelectedProtocol = new OptionalMethod<>(byte[].class, "getAlpnSelectedProtocol"); setAlpnProtocols = new OptionalMethod<>(null, "setAlpnProtocols", byte[].class); } return new AndroidPlatform(sslParametersClass, setUseSessionTickets, setHostname, getAlpnSelectedProtocol, setAlpnProtocols); } catch (ClassNotFoundException ignored) { // This isn't an Android runtime. } return null; }
@Override public void configureTlsExtensions( SSLSocket sslSocket, String hostname, List<Protocol> protocols) { // Enable SNI and session tickets. if (hostname != null) { setUseSessionTickets.invokeOptionalWithoutCheckedException(sslSocket, true); setHostname.invokeOptionalWithoutCheckedException(sslSocket, hostname); } // Enable ALPN. if (setAlpnProtocols != null && setAlpnProtocols.isSupported(sslSocket)) { Object[] parameters = {concatLengthPrefixed(protocols)}; setAlpnProtocols.invokeWithoutCheckedException(sslSocket, parameters); } }
/** * Returns true if the method exists on the supplied {@code target}. */ public boolean isSupported(T target) { return getMethod(target.getClass()) != null; }
/** * Invokes the method on {@code target} with {@code args}. If the method does not exist or is not * public then {@code null} is returned. See also {@link #invokeOptionalWithoutCheckedException}. * * @throws IllegalArgumentException if the arguments are invalid * @throws InvocationTargetException if the invocation throws an exception */ public Object invokeOptional(T target, Object... args) throws InvocationTargetException { Method m = getMethod(target.getClass()); if (m == null) { return null; } try { return m.invoke(target, args); } catch (IllegalAccessException e) { return null; } }
/** * Invokes the method on {@code target} with {@code args}. If the method does not exist or is not * public then {@code null} is returned. See also {@link #invokeOptionalWithoutCheckedException}. * * @throws IllegalArgumentException if the arguments are invalid * @throws InvocationTargetException if the invocation throws an exception */ public Object invokeOptional(T target, Object... args) throws InvocationTargetException { Method m = getMethod(target.getClass()); if (m == null) { return null; } try { return m.invoke(target, args); } catch (IllegalAccessException e) { return null; } }
/** * Invokes the method on {@code target} with {@code args}. Throws an error if the method is not * supported. See also {@link #invokeWithoutCheckedException(Object, Object...)}. * * @throws IllegalArgumentException if the arguments are invalid * @throws InvocationTargetException if the invocation throws an exception */ public Object invoke(T target, Object... args) throws InvocationTargetException { Method m = getMethod(target.getClass()); if (m == null) { throw new AssertionError("Method " + methodName + " not supported for object " + target); } try { return m.invoke(target, args); } catch (IllegalAccessException e) { // Method should be public: we checked. AssertionError error = new AssertionError("Unexpectedly could not call: " + m); error.initCause(e); throw error; } }
/** * Invokes the method on {@code target} with {@code args}. Throws an error if the method is not * supported. See also {@link #invokeWithoutCheckedException(Object, Object...)}. * * @throws IllegalArgumentException if the arguments are invalid * @throws InvocationTargetException if the invocation throws an exception */ public Object invoke(T target, Object... args) throws InvocationTargetException { Method m = getMethod(target.getClass()); if (m == null) { throw new AssertionError("Method " + methodName + " not supported for object " + target); } try { return m.invoke(target, args); } catch (IllegalAccessException e) { // Method should be public: we checked. AssertionError error = new AssertionError("Unexpectedly could not call: " + m); error.initCause(e); throw error; } }