1/*
2 * Copyright (c) 2015, 2017, 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
26package com.sun.xml.internal.ws.api.pipe;
27
28import java.lang.reflect.Constructor;
29import java.security.AccessController;
30import java.security.PrivilegedAction;
31import java.util.concurrent.ThreadFactory;
32
33/**
34 * Simple utility class to instantiate correct Thread instance
35 * depending on Java version.
36 *
37 * @author miroslav.kos@oracle.com
38 */
39final class ThreadHelper {
40
41    private static final String SAFE_THREAD_NAME = "sun.misc.ManagedLocalsThread";
42
43    private static final ThreadFactory threadFactory;
44
45    // no instantiating wanted
46    private ThreadHelper() {
47    }
48
49    static {
50        threadFactory = AccessController.doPrivileged(
51                new PrivilegedAction<ThreadFactory> () {
52                    @Override
53                    public ThreadFactory run() {
54                        // In order of preference
55                        try {
56                            try {
57                                Class<Thread> cls = Thread.class;
58                                Constructor<Thread> ctr = cls.getConstructor(
59                                        ThreadGroup.class,
60                                        Runnable.class,
61                                        String.class,
62                                        long.class,
63                                        boolean.class);
64                                return new JDK9ThreadFactory(ctr);
65                            } catch (NoSuchMethodException ignored) {
66                                // constructor newly added in Java SE 9
67                            }
68                            Class<?> cls = Class.forName(SAFE_THREAD_NAME);
69                            Constructor<?> ctr = cls.getConstructor(Runnable.class);
70                            return new SunMiscThreadFactory(ctr);
71                        } catch (ClassNotFoundException | NoSuchMethodException ignored) {}
72                        return new LegacyThreadFactory();
73                    }
74                }
75        );
76    }
77
78    static Thread createNewThread(final Runnable r) {
79        return threadFactory.newThread(r);
80    }
81
82    // A Thread factory backed by the Thread constructor that
83    // suppresses inheriting of inheritable thread-locals.
84    private static class JDK9ThreadFactory implements ThreadFactory {
85        final Constructor<Thread> ctr;
86        JDK9ThreadFactory(Constructor<Thread> ctr) { this.ctr = ctr; }
87        @Override public Thread newThread(Runnable r) {
88            try {
89                return ctr.newInstance(null, r, "toBeReplaced", 0, false);
90            } catch (ReflectiveOperationException x) {
91                InternalError ie = new InternalError(x.getMessage());
92                ie.initCause(ie);
93                throw ie;
94            }
95        }
96    }
97
98    // A Thread factory backed by sun.misc.ManagedLocalsThread
99    private static class SunMiscThreadFactory implements ThreadFactory {
100        final Constructor<?> ctr;
101        SunMiscThreadFactory(Constructor<?> ctr) { this.ctr = ctr; }
102        @Override public Thread newThread(final Runnable r) {
103            return AccessController.doPrivileged(
104                    new PrivilegedAction<Thread>() {
105                        @Override
106                        public Thread run() {
107                            try {
108                                return (Thread) ctr.newInstance(r);
109                            } catch (Exception e) {
110                                return new Thread(r);
111                            }
112                        }
113                    }
114            );
115        }
116    }
117
118    // A Thread factory backed by new Thread(Runnable)
119    private static class LegacyThreadFactory implements ThreadFactory {
120        @Override public Thread newThread(Runnable r) {
121            return new Thread(r);
122        }
123    }
124}
125