DefaultDatagramSocketImplFactory.java revision 12745:f068a4ffddd2
1/*
2 * Copyright (c) 2007, 2015, 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 */
25package java.net;
26
27import java.security.AccessController;
28import java.security.PrivilegedAction;
29
30/**
31 * This class defines a factory for creating DatagramSocketImpls. It defaults
32 * to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls
33 * by setting the impl.prefix system property.
34 *
35 * For Windows versions lower than Windows Vista a TwoStacksPlainDatagramSocketImpl
36 * is always created. This impl supports IPv6 on these platform where available.
37 *
38 * On Windows platforms greater than Vista that support a dual layer TCP/IP stack
39 * a DualStackPlainDatagramSocketImpl is created for DatagramSockets. For MulticastSockets
40 * a TwoStacksPlainDatagramSocketImpl is always created. This is to overcome the lack
41 * of behavior defined for multicasting over a dual layer socket by the RFC.
42 *
43 * @author Chris Hegarty
44 */
45
46class DefaultDatagramSocketImplFactory
47{
48    private static final Class<?> prefixImplClass;
49
50    /* the windows version. */
51    private static float version;
52
53    /* java.net.preferIPv4Stack */
54    private static boolean preferIPv4Stack = false;
55
56    /* If the version supports a dual stack TCP implementation */
57    private static final boolean useDualStackImpl;
58
59    /* sun.net.useExclusiveBind */
60    private static String exclBindProp;
61
62    /* True if exclusive binding is on for Windows */
63    private static final boolean exclusiveBind;
64
65    static {
66        Class<?> prefixImplClassLocal = null;
67        boolean useDualStackImplLocal = false;
68        boolean exclusiveBindLocal = true;
69
70        // Determine Windows Version.
71        java.security.AccessController.doPrivileged(
72                new PrivilegedAction<Object>() {
73                    public Object run() {
74                        version = 0;
75                        try {
76                            version = Float.parseFloat(System.getProperties()
77                                    .getProperty("os.version"));
78                            preferIPv4Stack = Boolean.parseBoolean(
79                                              System.getProperties()
80                                              .getProperty(
81                                                   "java.net.preferIPv4Stack"));
82                            exclBindProp = System.getProperty(
83                                    "sun.net.useExclusiveBind");
84                        } catch (NumberFormatException e) {
85                            assert false : e;
86                        }
87                        return null; // nothing to return
88                    }
89                });
90
91        // (version >= 6.0) implies Vista or greater.
92        if (version >= 6.0 && !preferIPv4Stack) {
93            useDualStackImplLocal = true;
94        }
95        if (exclBindProp != null) {
96            // sun.net.useExclusiveBind is true
97            exclusiveBindLocal = exclBindProp.length() == 0 ? true
98                    : Boolean.parseBoolean(exclBindProp);
99        } else if (version < 6.0) {
100            exclusiveBindLocal = false;
101        }
102
103        // impl.prefix
104        String prefix = null;
105        try {
106            prefix = AccessController.doPrivileged(
107                new sun.security.action.GetPropertyAction("impl.prefix", null));
108            if (prefix != null)
109                prefixImplClassLocal = Class.forName("java.net."+prefix+"DatagramSocketImpl");
110        } catch (Exception e) {
111            System.err.println("Can't find class: java.net." +
112                                prefix +
113                                "DatagramSocketImpl: check impl.prefix property");
114        }
115
116        prefixImplClass = prefixImplClassLocal;
117        useDualStackImpl = useDualStackImplLocal;
118        exclusiveBind = exclusiveBindLocal;
119    }
120
121    /**
122     * Creates a new <code>DatagramSocketImpl</code> instance.
123     *
124     * @param   isMulticast true if this impl is to be used for a MutlicastSocket
125     * @return  a new instance of <code>PlainDatagramSocketImpl</code>.
126     */
127    static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast)
128        throws SocketException {
129        if (prefixImplClass != null) {
130            try {
131                return (DatagramSocketImpl) prefixImplClass.newInstance();
132            } catch (Exception e) {
133                throw new SocketException("can't instantiate DatagramSocketImpl");
134            }
135        } else {
136            if (useDualStackImpl && !isMulticast)
137                return new DualStackPlainDatagramSocketImpl(exclusiveBind);
138            else
139                return new TwoStacksPlainDatagramSocketImpl(exclusiveBind && !isMulticast);
140        }
141    }
142}
143