1 /*
  2  * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package sun.rmi.runtime;
 27 
 28 import java.security.AccessController;
 29 import java.security.PrivilegedAction;
 30 import sun.security.util.SecurityConstants;
 31 
 32 /**
 33  * A PrivilegedAction for creating a new thread conveniently with an
 34  * AccessController.doPrivileged construct.
 35  *
 36  * All constructors allow the choice of the Runnable for the new
 37  * thread to execute, the name of the new thread (which will be
 38  * prefixed with "RMI "), and whether or not it will be a daemon
 39  * thread.
 40  *
 41  * The new thread may be created in the system thread group (the root
 42  * of the thread group tree) or an internally created non-system
 43  * thread group, as specified at construction of this class.
 44  *
 45  * The new thread will have the system class loader as its initial
 46  * context class loader (that is, its context class loader will NOT be
 47  * inherited from the current thread).
 48  *
 49  * @author      Peter Jones
 50  **/
 51 public final class NewThreadAction implements PrivilegedAction<Thread> {
 52 
 53     /** cached reference to the system (root) thread group */
 54     @SuppressWarnings("removal")
 55     static final ThreadGroup systemThreadGroup =
 56         AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
 57             public ThreadGroup run() {
 58                 @SuppressWarnings("deprecation")
 59                 ThreadGroup group = Thread.currentThread().getThreadGroup();
 60                 ThreadGroup parent;
 61                 while ((parent = group.getParent()) != null) {
 62                     group = parent;
 63                 }
 64                 return group;
 65             }
 66         });
 67 
 68     /**
 69      * special child of the system thread group for running tasks that
 70      * may execute user code, so that the security policy for threads in
 71      * the system thread group will not apply
 72      */
 73     @SuppressWarnings({"deprecation", "removal"})
 74     static final ThreadGroup userThreadGroup =
 75         AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
 76             public ThreadGroup run() {
 77                 return new ThreadGroup(systemThreadGroup, "RMI Runtime");
 78             }
 79         });
 80 
 81     private final ThreadGroup group;
 82     private final Runnable runnable;
 83     private final String name;
 84     private final boolean daemon;
 85 
 86     NewThreadAction(ThreadGroup group, Runnable runnable,
 87                     String name, boolean daemon)
 88     {
 89         this.group = group;
 90         this.runnable = runnable;
 91         this.name = name;
 92         this.daemon = daemon;
 93     }
 94 
 95     /**
 96      * Creates an action that will create a new thread in the
 97      * system thread group.
 98      *
 99      * @param   runnable the Runnable for the new thread to execute
100      *
101      * @param   name the name of the new thread
102      *
103      * @param   daemon if true, new thread will be a daemon thread;
104      * if false, new thread will not be a daemon thread
105      */
106     public NewThreadAction(Runnable runnable, String name, boolean daemon) {
107         this(systemThreadGroup, runnable, name, daemon);
108     }
109 
110     /**
111      * Creates an action that will create a new thread.
112      *
113      * @param   runnable the Runnable for the new thread to execute
114      *
115      * @param   name the name of the new thread
116      *
117      * @param   daemon if true, new thread will be a daemon thread;
118      * if false, new thread will not be a daemon thread
119      *
120      * @param   user if true, thread will be created in a non-system
121      * thread group; if false, thread will be created in the system
122      * thread group
123      */
124     public NewThreadAction(Runnable runnable, String name, boolean daemon,
125                            boolean user)
126     {
127         this(user ? userThreadGroup : systemThreadGroup,
128              runnable, name, daemon);
129     }
130 
131     public Thread run() {
132         @SuppressWarnings("removal")
133         SecurityManager sm = System.getSecurityManager();
134         if (sm != null) {
135             sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
136         }
137         Thread t = new Thread(group, runnable, "RMI " + name);
138         t.setContextClassLoader(ClassLoader.getSystemClassLoader());
139         t.setDaemon(daemon);
140         return t;
141     }
142 }
--- EOF ---