Skip to content

Commit 7cdfb6d

Browse files
committed
Merge pull request #3438 from akarnokd/ExceptionNullSafety
Better null tolerance in rx.exceptions.*Exception classes.
2 parents 860e79f + 130fcbe commit 7cdfb6d

File tree

7 files changed

+161
-15
lines changed

7 files changed

+161
-15
lines changed

src/main/java/rx/exceptions/MissingBackpressureException.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,17 @@ public class MissingBackpressureException extends Exception {
4848

4949
private static final long serialVersionUID = 7250870679677032194L;
5050

51+
/**
52+
* Constructs the exception without any custom message.
53+
*/
5154
public MissingBackpressureException() {
55+
5256
}
5357

58+
/**
59+
* Constructs the exception with the given customized message.
60+
* @param message the customized message
61+
*/
5462
public MissingBackpressureException(String message) {
5563
super(message);
5664
}

src/main/java/rx/exceptions/OnCompletedFailedException.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,35 @@
1515
*/
1616
package rx.exceptions;
1717

18+
import rx.Subscriber;
19+
20+
/**
21+
* Represents an exception used to re-throw errors thrown from {@link Subscriber#onCompleted()}.
22+
*/
1823
public final class OnCompletedFailedException extends RuntimeException {
1924

2025
private static final long serialVersionUID = 8622579378868820554L;
2126

27+
/**
28+
* Wraps the {@code Throwable} before it is to be re-thrown as an {@code OnCompletedFailedException}.
29+
*
30+
* @param e
31+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
32+
*/
2233
public OnCompletedFailedException(Throwable throwable) {
23-
super(throwable);
34+
super(throwable != null ? throwable : new NullPointerException());
2435
}
2536

37+
/**
38+
* Customizes the {@code Throwable} with a custom message and wraps it before it is to be re-thrown as an
39+
* {@code OnCompletedFailedException}.
40+
*
41+
* @param message
42+
* the message to assign to the {@code Throwable} to re-throw
43+
* @param e
44+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
45+
*/
2646
public OnCompletedFailedException(String message, Throwable throwable) {
27-
super(message, throwable);
47+
super(message, throwable != null ? throwable : new NullPointerException());
2848
}
2949
}

src/main/java/rx/exceptions/OnErrorFailedException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ public class OnErrorFailedException extends RuntimeException {
3232
* @param message
3333
* the message to assign to the {@code Throwable} to re-throw
3434
* @param e
35-
* the {@code Throwable} to re-throw
35+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
3636
*/
3737
public OnErrorFailedException(String message, Throwable e) {
38-
super(message, e);
38+
super(message, e != null ? e : new NullPointerException());
3939
}
4040

4141
/**
4242
* Wraps the {@code Throwable} before it is to be re-thrown as an {@code OnErrorFailedException}.
4343
*
4444
* @param e
45-
* the {@code Throwable} to re-throw
45+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
4646
*/
4747
public OnErrorFailedException(Throwable e) {
48-
super(e.getMessage(), e);
48+
super(e != null ? e.getMessage() : null, e != null ? e : new NullPointerException());
4949
}
5050
}

src/main/java/rx/exceptions/OnErrorNotImplementedException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,19 @@ public class OnErrorNotImplementedException extends RuntimeException {
4040
* @param message
4141
* the message to assign to the {@code Throwable} to re-throw
4242
* @param e
43-
* the {@code Throwable} to re-throw
43+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
4444
*/
4545
public OnErrorNotImplementedException(String message, Throwable e) {
46-
super(message, e);
46+
super(message, e != null ? e : new NullPointerException());
4747
}
4848

4949
/**
5050
* Wraps the {@code Throwable} before it is to be re-thrown as an {@code OnErrorNotImplementedException}.
5151
*
5252
* @param e
53-
* the {@code Throwable} to re-throw
53+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
5454
*/
5555
public OnErrorNotImplementedException(Throwable e) {
56-
super(e.getMessage(), e);
56+
super(e != null ? e.getMessage() : null, e != null ? e : new NullPointerException());
5757
}
5858
}

src/main/java/rx/exceptions/OnErrorThrowable.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,18 @@ public boolean isValueNull() {
6969
* Converts a {@link Throwable} into an {@link OnErrorThrowable}.
7070
*
7171
* @param t
72-
* the {@code Throwable} to convert
72+
* the {@code Throwable} to convert; if null, a NullPointerException is constructed
7373
* @return an {@code OnErrorThrowable} representation of {@code t}
7474
*/
7575
public static OnErrorThrowable from(Throwable t) {
76+
if (t == null) {
77+
t = new NullPointerException();
78+
}
7679
Throwable cause = Exceptions.getFinalCause(t);
7780
if (cause instanceof OnErrorThrowable.OnNextValue) {
7881
return new OnErrorThrowable(t, ((OnNextValue) cause).getValue());
79-
} else {
80-
return new OnErrorThrowable(t);
8182
}
83+
return new OnErrorThrowable(t);
8284
}
8385

8486
/**
@@ -93,6 +95,9 @@ public static OnErrorThrowable from(Throwable t) {
9395
* cause
9496
*/
9597
public static Throwable addValueAsLastCause(Throwable e, Object value) {
98+
if (e == null) {
99+
e = new NullPointerException();
100+
}
96101
Throwable lastCause = Exceptions.getFinalCause(e);
97102
if (lastCause != null && lastCause instanceof OnNextValue) {
98103
// purposefully using == for object reference check

src/main/java/rx/exceptions/UnsubscribeFailedException.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,36 @@
1515
*/
1616
package rx.exceptions;
1717

18+
import rx.Subscriber;
19+
20+
/**
21+
* Represents an exception used to re-throw errors thrown from {@link Subscriber#unsubscribe()}.
22+
*/
1823
public final class UnsubscribeFailedException extends RuntimeException {
1924

2025
private static final long serialVersionUID = 4594672310593167598L;
2126

27+
/**
28+
* Wraps the {@code Throwable} before it is to be re-thrown as an {@code OnErrorFailedException}.
29+
*
30+
* @param throwable
31+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
32+
*/
2233
public UnsubscribeFailedException(Throwable throwable) {
23-
super(throwable);
34+
super(throwable != null ? throwable : new NullPointerException());
2435
}
2536

37+
/**
38+
* Customizes the {@code Throwable} with a custom message and wraps it before it is to be re-thrown as an
39+
* {@code UnsubscribeFailedException}.
40+
*
41+
* @param message
42+
* the message to assign to the {@code Throwable} to re-throw
43+
* @param throwable
44+
* the {@code Throwable} to re-throw; if null, a NullPointerException is constructed
45+
*/
2646
public UnsubscribeFailedException(String message, Throwable throwable) {
27-
super(message, throwable);
47+
super(message, throwable != null ? throwable : new NullPointerException());
2848
}
2949

3050
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* Copyright 2014 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.exceptions;
17+
18+
import org.junit.*;
19+
20+
/**
21+
* Checks the Exception classes to verify they don't crash with null argument
22+
*/
23+
public class ExceptionsNullTest {
24+
25+
@Test
26+
public void testOnCompleteFailedExceptionNull() {
27+
Throwable t = new OnCompletedFailedException(null);
28+
29+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
30+
}
31+
32+
@Test
33+
public void testOnCompleteFailedExceptionMessageAndNull() {
34+
Throwable t = new OnCompletedFailedException("Message", null);
35+
36+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
37+
}
38+
39+
@Test
40+
public void testOnErrorFailedExceptionNull() {
41+
Throwable t = new OnErrorFailedException(null);
42+
43+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
44+
}
45+
46+
@Test
47+
public void testOnErrorFailedExceptionMessageAndNull() {
48+
Throwable t = new OnErrorFailedException("Message", null);
49+
50+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
51+
}
52+
53+
@Test
54+
public void testUnsubscribeFailedExceptionNull() {
55+
Throwable t = new UnsubscribeFailedException(null);
56+
57+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
58+
}
59+
60+
@Test
61+
public void testUnsubscribeFailedExceptionMessageAndNull() {
62+
Throwable t = new UnsubscribeFailedException("Message", null);
63+
64+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
65+
}
66+
67+
@Test
68+
public void testOnErrorNotImplementedExceptionNull() {
69+
Throwable t = new OnErrorNotImplementedException(null);
70+
71+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
72+
}
73+
74+
@Test
75+
public void testOnErrorNotImplementedExceptionMessageAndNull() {
76+
Throwable t = new OnErrorNotImplementedException("Message", null);
77+
78+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
79+
}
80+
81+
@Test
82+
public void testOnErrorThrowableFrom() {
83+
Throwable t = OnErrorThrowable.from(null);
84+
Assert.assertTrue(t.getCause() instanceof NullPointerException);
85+
}
86+
87+
@Test
88+
public void testOnErrorThrowableAddValueAsLastCause() {
89+
Throwable t = OnErrorThrowable.addValueAsLastCause(null, "value");
90+
Assert.assertTrue(t instanceof NullPointerException);
91+
}
92+
93+
}

0 commit comments

Comments
 (0)