/** * Gets the method to invoke trying to minimize the cost of reflection reusing objects cached * in static members. * * @param socket Instance of the socket to use in connection with server. * @return Method to call to set a write timeout in the socket. */ private static Method getMethod(Socket socket) { final Class<?> socketClass = socket.getClass(); final WriteTimeoutEnforcer instance = mSingleInstance.get(); if (instance == null) { return initFrom(socketClass); } else if (instance.mSocketClassRef.get() != socketClass) { // the underlying class changed return initFrom(socketClass); } else if (instance.mSetSoWriteTimeoutMethodRef == null) { // method not supported return null; } else { final Method cachedSetSoWriteTimeoutMethod = instance.mSetSoWriteTimeoutMethodRef.get(); return (cachedSetSoWriteTimeoutMethod == null) ? initFrom(socketClass) : cachedSetSoWriteTimeoutMethod ; } }
/** * Singleton initializer. * * Uses reflection to extract and 'cache' the method to invoke to set a write timouet in a socket. * * @param socketClass Underlying class providing the implementation of {@link Socket}. * @return Method to call to set a write timeout in the socket. */ private static Method initFrom(Class<?> socketClass) { Log_OC.i(TAG, "Socket implementation: " + socketClass.getCanonicalName()); Method setSoWriteTimeoutMethod = null; try { setSoWriteTimeoutMethod = socketClass.getMethod(METHOD_NAME, int.class); } catch (SecurityException e) { Log_OC.e(TAG, "Could not access to (SocketImpl)#setSoWriteTimeout(int) method ", e); } catch (NoSuchMethodException e) { Log_OC.i( TAG, "Could not find (SocketImpl)#setSoWriteTimeout(int) method - write timeout not supported" ); } mSingleInstance.set(new WriteTimeoutEnforcer(socketClass, setSoWriteTimeoutMethod)); return setSoWriteTimeoutMethod; }
/** * Calls the {@code #setSoWrite(int)} method of the underlying implementation * of {@link Socket} if exists. * Creates and initializes the single instance of the class when needed * * @param writeTimeoutMilliseconds Write timeout to set, in milliseconds. * @param socket Client socket to connect with the server. */ public static void setSoWriteTimeout(int writeTimeoutMilliseconds, Socket socket) { final Method setSoWriteTimeoutMethod = getMethod(socket); if (setSoWriteTimeoutMethod != null) { try { setSoWriteTimeoutMethod.invoke(socket, writeTimeoutMilliseconds); Log_OC.i( TAG, "Write timeout set in socket, writeTimeoutMilliseconds: " + writeTimeoutMilliseconds ); } catch (IllegalArgumentException e) { Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e); } catch (IllegalAccessException e) { Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e); } catch (InvocationTargetException e) { Log_OC.e(TAG, "Call to (SocketImpl)#setSoWriteTimeout(int) failed ", e); } } else { Log_OC.i(TAG, "Write timeout for socket not supported"); } }