@@ -105,7 +105,7 @@ public void reset() {
105105 public RxJavaErrorHandler getErrorHandler () {
106106 if (errorHandler .get () == null ) {
107107 // check for an implementation from System.getProperty first
108- Object impl = getPluginImplementationViaProperty (RxJavaErrorHandler .class , System . getProperties ());
108+ Object impl = getPluginImplementationViaProperty (RxJavaErrorHandler .class , getSystemPropertiesSafe ());
109109 if (impl == null ) {
110110 // nothing set via properties so initialize with default
111111 errorHandler .compareAndSet (null , DEFAULT_ERROR_HANDLER );
@@ -147,7 +147,7 @@ public void registerErrorHandler(RxJavaErrorHandler impl) {
147147 public RxJavaObservableExecutionHook getObservableExecutionHook () {
148148 if (observableExecutionHook .get () == null ) {
149149 // check for an implementation from System.getProperty first
150- Object impl = getPluginImplementationViaProperty (RxJavaObservableExecutionHook .class , System . getProperties ());
150+ Object impl = getPluginImplementationViaProperty (RxJavaObservableExecutionHook .class , getSystemPropertiesSafe ());
151151 if (impl == null ) {
152152 // nothing set via properties so initialize with default
153153 observableExecutionHook .compareAndSet (null , RxJavaObservableExecutionHookDefault .getInstance ());
@@ -189,7 +189,7 @@ public void registerObservableExecutionHook(RxJavaObservableExecutionHook impl)
189189 public RxJavaSingleExecutionHook getSingleExecutionHook () {
190190 if (singleExecutionHook .get () == null ) {
191191 // check for an implementation from System.getProperty first
192- Object impl = getPluginImplementationViaProperty (RxJavaSingleExecutionHook .class , System . getProperties ());
192+ Object impl = getPluginImplementationViaProperty (RxJavaSingleExecutionHook .class , getSystemPropertiesSafe ());
193193 if (impl == null ) {
194194 // nothing set via properties so initialize with default
195195 singleExecutionHook .compareAndSet (null , RxJavaSingleExecutionHookDefault .getInstance ());
@@ -232,7 +232,7 @@ public void registerSingleExecutionHook(RxJavaSingleExecutionHook impl) {
232232 public RxJavaCompletableExecutionHook getCompletableExecutionHook () {
233233 if (completableExecutionHook .get () == null ) {
234234 // check for an implementation from System.getProperty first
235- Object impl = getPluginImplementationViaProperty (RxJavaCompletableExecutionHook .class , System . getProperties ());
235+ Object impl = getPluginImplementationViaProperty (RxJavaCompletableExecutionHook .class , getSystemPropertiesSafe ());
236236 if (impl == null ) {
237237 // nothing set via properties so initialize with default
238238 completableExecutionHook .compareAndSet (null , new RxJavaCompletableExecutionHook () { });
@@ -262,6 +262,19 @@ public void registerCompletableExecutionHook(RxJavaCompletableExecutionHook impl
262262 }
263263 }
264264
265+ /**
266+ * A security manager may prevent accessing the System properties entirely,
267+ * therefore, the SecurityException is turned into an empty properties.
268+ * @return the Properties to use for looking up settings
269+ */
270+ /* test */ static Properties getSystemPropertiesSafe () {
271+ try {
272+ return System .getProperties ();
273+ } catch (SecurityException ex ) {
274+ return new Properties ();
275+ }
276+ }
277+
265278 /* test */ static Object getPluginImplementationViaProperty (Class <?> pluginClass , Properties propsIn ) {
266279 // Make a defensive clone because traversal may fail with ConcurrentModificationException
267280 // if the properties get changed by something outside RxJava.
@@ -284,25 +297,32 @@ public void registerCompletableExecutionHook(RxJavaCompletableExecutionHook impl
284297 String classSuffix = ".class" ;
285298 String implSuffix = ".impl" ;
286299
287- for (Map .Entry <Object , Object > e : props .entrySet ()) {
288- String key = e .getKey ().toString ();
289- if (key .startsWith (pluginPrefix ) && key .endsWith (classSuffix )) {
290- String value = e .getValue ().toString ();
300+ try {
301+ for (Map .Entry <Object , Object > e : props .entrySet ()) {
302+ String key = e .getKey ().toString ();
303+ if (key .startsWith (pluginPrefix ) && key .endsWith (classSuffix )) {
304+ String value = e .getValue ().toString ();
305+
306+ if (classSimpleName .equals (value )) {
307+ String index = key .substring (0 , key .length () - classSuffix .length ()).substring (pluginPrefix .length ());
291308
292- if (classSimpleName .equals (value )) {
293- String index = key .substring (0 , key .length () - classSuffix .length ()).substring (pluginPrefix .length ());
309+ String implKey = pluginPrefix + index + implSuffix ;
294310
295- String implKey = pluginPrefix + index + implSuffix ;
311+ implementingClass = props . getProperty ( implKey ) ;
296312
297- implementingClass = props .getProperty (implKey );
313+ if (implementingClass == null ) {
314+ throw new IllegalStateException ("Implementing class declaration for " + classSimpleName + " missing: " + implKey );
315+ }
298316
299- if (implementingClass == null ) {
300- throw new IllegalStateException ("Implementing class declaration for " + classSimpleName + " missing: " + implKey );
317+ break ;
301318 }
302-
303- break ;
304319 }
305320 }
321+ } catch (SecurityException ex ) {
322+ // https://github.com/ReactiveX/RxJava/issues/5819
323+ // We don't seem to have access to all properties.
324+ // At least print the exception to the console.
325+ ex .printStackTrace ();
306326 }
307327 }
308328
@@ -339,7 +359,7 @@ public void registerCompletableExecutionHook(RxJavaCompletableExecutionHook impl
339359 public RxJavaSchedulersHook getSchedulersHook () {
340360 if (schedulersHook .get () == null ) {
341361 // check for an implementation from System.getProperty first
342- Object impl = getPluginImplementationViaProperty (RxJavaSchedulersHook .class , System . getProperties ());
362+ Object impl = getPluginImplementationViaProperty (RxJavaSchedulersHook .class , getSystemPropertiesSafe ());
343363 if (impl == null ) {
344364 // nothing set via properties so initialize with default
345365 schedulersHook .compareAndSet (null , RxJavaSchedulersHook .getDefaultInstance ());
0 commit comments