001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Mikhail A. Markov
021: * @version $Revision: 1.1.2.2 $
022: */package org.apache.harmony.rmi.common;
023:
024: import java.security.AccessController;
025: import java.security.PrivilegedAction;
026:
027: /**
028: * Action for privileged Threads creation.
029: * There are 2 ThreadGroups used in RMI runtime:
030: * 1) System ThreadGroup, i.e. the topmost non-null ThreadGroup. All RMI
031: * internal threads are created in this group
032: * 2) Non-system ThreadGroup, i.e. the child of the system ThreadGroup. There
033: * are 2 cases when the thread is created in this group:
034: * a) When the remote call is accepted on the server side
035: * b) When the unreferenced thread is started
036: *
037: * There are 2 reasons why 2 threads are needed:
038: * 1) If we create all threads in the system ThreadGroup than if the
039: * implementation of remote method has the code starting the new thread,
040: * we'll get AccessControllException requiring
041: * java.lang.RuntimePermission("modifyThreadGroup") and
042: * java.lang.RuntimePermission("modifyThread") permissions because it's not
043: * allowed by default to create a new thread in the system group
044: * 2) If we create all threads (including RMI internal ones) in non-system
045: * ThreadGroup then the malicious code could potentially interrupt RMI
046: * internal threads by using Thread.enumerate() static method.
047: *
048: * @author Mikhail A. Markov
049: * @version $Revision: 1.1.2.2 $
050: */
051: public class CreateThreadAction implements PrivilegedAction {
052: /*
053: * System ThreadGroup, i.e. the topmost non-null ThreadGroup.
054: */
055: private static final ThreadGroup systemGroup = (ThreadGroup) AccessController
056: .doPrivileged(new PrivilegedAction() {
057: public Object run() {
058: ThreadGroup tg = Thread.currentThread()
059: .getThreadGroup();
060: ThreadGroup tg1 = tg.getParent();
061:
062: while (tg1 != null) {
063: tg = tg1;
064: tg1 = tg.getParent();
065: }
066: return tg;
067: }
068: });
069:
070: /*
071: * Non-system ThreadGroup: child of the system ThreadGroup.
072: */
073: private static final ThreadGroup nonSystemGroup = (ThreadGroup) AccessController
074: .doPrivileged(new PrivilegedAction() {
075: public Object run() {
076: return new ThreadGroup(systemGroup, "RMI Group"); //$NON-NLS-1$
077: }
078: });
079:
080: // Runnable object for Thread creation.
081: private Runnable r;
082:
083: // The name of thread to be created.
084: private String name;
085:
086: // True if thread to be created should be a daemon.
087: private boolean isDaemon;
088:
089: // True if thread to be created should be in the system ThreadGroup.
090: private boolean isSystem;
091:
092: /**
093: * Constructs CreateThreadAction to create a new Thread in the system
094: * ThreadGroup.
095: *
096: * @param r Runnable object for Thread creation
097: * @param name name of thread to be created
098: * @param isDaemon true if thread to be created should be a daemon
099: */
100: public CreateThreadAction(Runnable r, String name, boolean isDaemon) {
101: this (r, name, isDaemon, true);
102: }
103:
104: /**
105: * Constructs CreateThreadAction to create Thread.
106: *
107: * @param r Runnable object for Thread creation
108: * @param name name of thread to be created
109: * @param isDaemon true if thread to be created should be a daemon
110: * @param isSystem true if system ThreadGroup should be used and false
111: * otherwise
112: */
113: public CreateThreadAction(Runnable r, String name,
114: boolean isDaemon, boolean isSystem) {
115: this .r = r;
116: this .name = name;
117: this .isDaemon = isDaemon;
118: this .isSystem = isSystem;
119: }
120:
121: /**
122: * Creates the thread.
123: *
124: * @return started thread
125: */
126: public Object run() {
127: Thread t = new Thread(isSystem ? systemGroup : nonSystemGroup,
128: r, name);
129: t.setContextClassLoader(ClassLoader.getSystemClassLoader());
130: t.setDaemon(isDaemon);
131: return t;
132: }
133: }
|