1717
1818import java .lang .reflect .Method ;
1919import java .time .Duration ;
20+ import java .util .Optional ;
2021import java .util .concurrent .CancellationException ;
2122import java .util .concurrent .CompletionException ;
2223import java .util .concurrent .CompletionStage ;
2324import java .util .concurrent .ExecutionException ;
2425import java .util .concurrent .Future ;
2526import java .util .concurrent .TimeoutException ;
2627import java .util .function .BiFunction ;
28+ import java .util .function .Function ;
2729import java .util .function .Supplier ;
30+ import java .util .stream .Stream ;
31+
2832
2933class SharedFunctions {
3034
@@ -68,25 +72,17 @@ static boolean cancelPromise(CompletionStage<?> promise, boolean mayInterruptIfR
6872 Future <?> future = (Future <?>) promise ;
6973 return future .cancel (mayInterruptIfRunning );
7074 } else {
71- Method m = completeExceptionallyMethodOf (promise );
72- if (null != m ) {
73- try {
74- return (Boolean ) m .invoke (promise , new CancellationException ());
75- } catch (final ReflectiveOperationException ex ) {
76- return false ;
77- }
78- } else {
79- return false ;
80- }
81- }
82- }
83-
84- private static Method completeExceptionallyMethodOf (CompletionStage <?> promise ) {
85- try {
86- Class <?> clazz = promise .getClass ();
87- return clazz .getMethod ("completeExceptionally" , Throwable .class );
88- } catch (ReflectiveOperationException | SecurityException ex ) {
89- return null ;
75+ Stream <Function <Class <?>, ExceptionalCancellation >> options = Stream .of (
76+ SharedFunctions ::cancelInterruptibleMethodOf ,
77+ SharedFunctions ::cancelMethodOf ,
78+ SharedFunctions ::completeExceptionallyMethodOf
79+ );
80+
81+ return options .map (f -> tryCancellation (f , promise , mayInterruptIfRunning ))
82+ .filter (Optional ::isPresent )
83+ .map (Optional ::get )
84+ .findFirst ()
85+ .orElse (Boolean .FALSE );
9086 }
9187 }
9288
@@ -113,6 +109,63 @@ static <T, E extends Throwable> T sneakyThrow(Throwable e) throws E {
113109 throw (E ) e ;
114110 }
115111
112+
113+ private static Optional <Boolean > tryCancellation (Function <Class <?>, ExceptionalCancellation > option ,
114+ CompletionStage <?> promise ,
115+ boolean mayInterruptIfRunning ) {
116+
117+
118+ return Optional .ofNullable ( option .apply (promise .getClass ()) )
119+ .map (SharedFunctions ::uncheckedReflectionException ) // TODO: False for reflective operation or runtime exception?
120+ .map (bf -> bf .apply (promise , mayInterruptIfRunning ? Boolean .TRUE : Boolean .FALSE ))
121+ ;
122+ }
123+
124+ private static ExceptionalCancellation completeExceptionallyMethodOf (Class <?> clazz ) {
125+ try {
126+ Method m = clazz .getMethod ("completeExceptionally" , Throwable .class );
127+ return (p , b ) -> (Boolean )m .invoke (p , new CancellationException ());
128+ } catch (ReflectiveOperationException | SecurityException ex ) {
129+ return null ;
130+ }
131+ }
132+
133+ private static ExceptionalCancellation cancelInterruptibleMethodOf (Class <?> clazz ) {
134+ try {
135+ Method m = clazz .getMethod ("cancel" , boolean .class );
136+ return (p , b ) -> (Boolean )m .invoke (p , b );
137+ } catch (ReflectiveOperationException | SecurityException ex ) {
138+ return null ;
139+ }
140+ }
141+
142+ private static ExceptionalCancellation cancelMethodOf (Class <?> clazz ) {
143+ try {
144+ Method m = clazz .getMethod ("cancel" );
145+ return (p , b ) -> (Boolean )m .invoke (p );
146+ } catch (ReflectiveOperationException | SecurityException ex ) {
147+ return null ;
148+ }
149+ }
150+
151+ private static <T , U > Cancellation uncheckedReflectionException (ExceptionalCancellation original ) {
152+ return (a , b ) -> {
153+ try {
154+ return original .apply (a , b );
155+ } catch (ReflectiveOperationException ex ) {
156+ throw new RuntimeException (ex );
157+ }
158+ };
159+ }
160+
116161 private static final BiFunction <Object , Object , Object > SELECT_FIRST = (u , v ) -> u ;
117162 private static final BiFunction <Object , Object , Object > SELECT_SECOND = (u , v ) -> v ;
163+
164+ @ FunctionalInterface
165+ private static interface Cancellation extends BiFunction <CompletionStage <?>, Boolean , Boolean > { }
166+
167+ @ FunctionalInterface
168+ public interface ExceptionalCancellation {
169+ Boolean apply (CompletionStage <?> p , Boolean b ) throws ReflectiveOperationException ;
170+ }
118171}
0 commit comments