01: /*
02: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
03: * notice. All rights reserved.
04: */
05: package com.tc.lang;
06:
07: import com.tc.util.runtime.Vm;
08:
09: import java.lang.reflect.Field;
10:
11: /**
12: * The purpose of this class to execute a startup action (ie. "start the server", or "start the client", etc) in the
13: * specified thread group. The side effect of doing this is that any more threads spawned by the startup action will
14: * inherit the given thread group. It is somewhat fragile, and sometimes impossible (see java.util.Timer) to be explicit
15: * about the thread group when spawning threads <br>
16: * <br>
17: * XXX: At the moment, this class uses a hack of adjusting the current thread's group to the desired target group. A
18: * nicer approach would be to start a new thread in the desiered target group and run the action in that thread and
19: * join() it, except that can introduce locking problems (see MNK-65)
20: */
21: public class StartupHelper {
22:
23: private final StartupAction action;
24: private final ThreadGroup targetThreadGroup;
25:
26: public StartupHelper(ThreadGroup threadGroup, StartupAction action) {
27: this .targetThreadGroup = threadGroup;
28: this .action = action;
29: }
30:
31: public void startUp() {
32: Thread currentThread = Thread.currentThread();
33: ThreadGroup origThreadGroup = currentThread.getThreadGroup();
34:
35: setThreadGroup(currentThread, targetThreadGroup);
36:
37: Throwable actionError = null;
38: try {
39: action.execute();
40: } catch (Throwable t) {
41: actionError = t;
42: } finally {
43: setThreadGroup(currentThread, origThreadGroup);
44: }
45:
46: if (actionError != null) {
47: targetThreadGroup.uncaughtException(currentThread,
48: actionError);
49: }
50: }
51:
52: public interface StartupAction {
53: void execute() throws Throwable;
54: }
55:
56: private static void setThreadGroup(Thread thread, ThreadGroup group) {
57: String fieldName = Vm.isIBM() ? "threadGroup" : "group";
58: Class c = Thread.class;
59:
60: try {
61: Field groupField = c.getDeclaredField(fieldName);
62: groupField.setAccessible(true);
63: groupField.set(thread, group);
64: } catch (Exception e) {
65: if (e instanceof RuntimeException) {
66: throw (RuntimeException) e;
67: }
68: throw new RuntimeException(e);
69: }
70: }
71: }
|