Make current subject more similar to future evolution of Java
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Jul 2022 07:37:45 +0000 (09:37 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Jul 2022 07:37:45 +0000 (09:37 +0200)
org.argeo.util/src/org/argeo/util/CurrentSubject.java

index d7627629fad89ad08ccaa315a984747d0541b56a..60ce3cf26ed5ad92a204609ed30a18a51c673a5f 100644 (file)
@@ -9,36 +9,57 @@ import java.util.concurrent.CompletionException;
 import javax.security.auth.Subject;
 
 /**
- * Prepare evotion of Java APIs introduced in JDK 18, as these static methods
+ * Prepare evolution of Java APIs introduced in JDK 18, as these static methods
  * will be added to {@link Subject}.
  */
 @SuppressWarnings("removal")
 public class CurrentSubject {
 
-       /** Singleton. */
-       private CurrentSubject() {
+       private final static boolean useThreadLocal = Boolean
+                       .parseBoolean(System.getProperty("jdk.security.auth.subject.useTL"));
 
-       }
+       private final static InheritableThreadLocal<Subject> current = new InheritableThreadLocal<>();
 
        public static Subject current() {
-               Subject subject = Subject.getSubject(AccessController.getContext());
-               if (subject == null)
-                       throw new IllegalStateException("Cannot find related subject");
-               return subject;
+               if (useThreadLocal) {
+                       return current.get();
+               } else {// legacy
+                       Subject subject = Subject.getSubject(AccessController.getContext());
+                       return subject;
+               }
        }
 
        public static <T> T callAs(Subject subject, Callable<T> action) {
-               try {
-                       return Subject.doAs(subject, new PrivilegedExceptionAction<T>() {
-       
-                               @Override
-                               public T run() throws Exception {
-                                       return action.call();
-                               }
-       
-                       });
-               } catch (PrivilegedActionException e) {
-                       throw new CompletionException("Failed to execute action for " + subject, e.getCause());
+               if (useThreadLocal) {
+                       Subject previous = current();
+                       current.set(subject);
+                       try {
+                               return action.call();
+                       } catch (Exception e) {
+                               throw new CompletionException("Failed to execute action for " + subject, e);
+                       } finally {
+                               current.set(previous);
+                       }
+               } else {// legacy
+                       try {
+                               return Subject.doAs(subject, new PrivilegedExceptionAction<T>() {
+
+                                       @Override
+                                       public T run() throws Exception {
+                                               return action.call();
+                                       }
+
+                               });
+                       } catch (PrivilegedActionException e) {
+                               throw new CompletionException("Failed to execute action for " + subject, e.getCause());
+                       } catch (Exception e) {
+                               throw new CompletionException("Failed to execute action for " + subject, e);
+                       }
                }
        }
+
+       /** Singleton. */
+       private CurrentSubject() {
+       }
+
 }